Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/animation_clean.py192
-rw-r--r--release/scripts/image_2d_cutout.py559
-rw-r--r--release/scripts/object_active_to_other.py58
-rw-r--r--release/scripts/scripttemplate_gamelogic_module.py45
-rw-r--r--release/scripts/textplugin_convert_ge.py863
-rw-r--r--release/scripts/wizard_bolt_factory.py2811
-rw-r--r--release/scripts/wizard_landscape_ant.py2148
-rw-r--r--release/ui/buttons_data_modifier.py12
-rw-r--r--release/ui/space_sequencer.py559
-rw-r--r--source/blender/blenkernel/BKE_action.h3
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h8
-rw-r--r--source/blender/blenkernel/BKE_nla.h55
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h1
-rw-r--r--source/blender/blenkernel/intern/action.c49
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c620
-rw-r--r--source/blender/blenkernel/intern/fcurve.c221
-rw-r--r--source/blender/blenkernel/intern/nla.c745
-rw-r--r--source/blender/blenkernel/intern/object.c8
-rw-r--r--source/blender/blenloader/intern/readfile.c156
-rw-r--r--source/blender/blenloader/intern/writefile.c130
-rw-r--r--source/blender/editors/animation/anim_channels.c68
-rw-r--r--source/blender/editors/animation/anim_filter.c691
-rw-r--r--source/blender/editors/animation/keyframes_draw.c2
-rw-r--r--source/blender/editors/animation/keyframes_edit.c24
-rw-r--r--source/blender/editors/include/ED_anim_api.h51
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/UI_view2d.h2
-rw-r--r--source/blender/editors/interface/resources.c19
-rw-r--r--source/blender/editors/interface/view2d.c23
-rw-r--r--source/blender/editors/screen/screen_ops.c6
-rw-r--r--source/blender/editors/space_action/action_select.c29
-rw-r--r--source/blender/editors/space_file/filesel.c3
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c5
-rw-r--r--source/blender/editors/space_graph/graph_select.c2
-rw-r--r--source/blender/editors/space_graph/space_graph.c2
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c399
-rw-r--r--source/blender/editors/space_nla/nla_channels.c424
-rw-r--r--source/blender/editors/space_nla/nla_draw.c793
-rw-r--r--source/blender/editors/space_nla/nla_edit.c699
-rw-r--r--source/blender/editors/space_nla/nla_header.c199
-rw-r--r--source/blender/editors/space_nla/nla_intern.h87
-rw-r--r--source/blender/editors/space_nla/nla_ops.c257
-rw-r--r--source/blender/editors/space_nla/nla_select.c600
-rw-r--r--source/blender/editors/space_nla/space_nla.c339
-rw-r--r--source/blender/editors/space_outliner/outliner.c14
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h1
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c1
-rw-r--r--source/blender/editors/transform/transform.c3
-rw-r--r--source/blender/editors/transform/transform.h7
-rw-r--r--source/blender/editors/transform/transform_conversions.c192
-rw-r--r--source/blender/editors/transform/transform_generics.c100
-rw-r--r--source/blender/editors/transform/transform_ops.c13
-rw-r--r--source/blender/makesdna/DNA_action_types.h11
-rw-r--r--source/blender/makesdna/DNA_anim_types.h140
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesdna/DNA_space_types.h6
-rw-r--r--source/blender/makesrna/RNA_access.h3
-rw-r--r--source/blender/makesrna/intern/makesrna.c1
-rw-r--r--source/blender/makesrna/intern/rna_animation.c2
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c1
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_nla.c349
-rw-r--r--source/blender/makesrna/intern/rna_object.c23
-rw-r--r--source/blender/makesrna/intern/rna_space.c28
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.cpp183
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.h107
-rw-r--r--source/gameengine/Ketsji/KX_PythonSeq.cpp453
-rw-r--r--source/gameengine/Ketsji/KX_PythonSeq.h60
-rw-r--r--source/gameengine/PyDoc/API_intro.py110
-rw-r--r--source/gameengine/SceneGraph/SG_DList.h161
-rw-r--r--source/gameengine/SceneGraph/SG_QList.h157
71 files changed, 6676 insertions, 9420 deletions
diff --git a/release/scripts/animation_clean.py b/release/scripts/animation_clean.py
deleted file mode 100644
index fc44f264ac1..00000000000
--- a/release/scripts/animation_clean.py
+++ /dev/null
@@ -1,192 +0,0 @@
-#!BPY
-
-"""
-Name: 'Clean Animation Curves'
-Blender: 249
-Group: 'Animation'
-Tooltip: 'Remove unused keyframes for ipo curves'
-"""
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# Copyright (C) 2008-2009: Blender Foundation
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# --------------------------------------------------------------------------
-
-import bpy
-from Blender import IpoCurve, Draw, Window
-
-def clean_ipos(ipos):
- eul = 0.001
-
- def isflat(vec):
- prev_y = vec[0][1]
- mid_y = vec[1][1]
- next_y = vec[2][1]
-
- # flat status for prev and next
- return abs(mid_y-prev_y) < eul, abs(mid_y-next_y) < eul
-
-
-
- X=0
- Y=1
- PREV=0
- MID=1
- NEXT=2
-
- LEFT = 0
- RIGHT = 1
-
- TOT = 0
- TOTBEZ = 0
- # for ipo in bpy.data.ipos:
- for ipo in ipos:
- if ipo.lib:
- continue
- # print ipo
- for icu in ipo:
- interp = icu.interpolation
- extend = icu.extend
-
- bezierPoints = icu.bezierPoints
- bezierVecs = [bez.vec for bez in bezierPoints]
-
- l = len(bezierPoints)
-
- TOTBEZ += l
-
- # our aim is to simplify this ipo as much as possible!
- if interp == IpoCurve.InterpTypes.BEZIER or interp == interp == IpoCurve.InterpTypes.LINEAR:
- #print "Not yet supported"
-
- if interp == IpoCurve.InterpTypes.BEZIER:
- flats = [isflat(bez) for bez in bezierVecs]
- else:
- # A bit of a waste but fake the locations for these so they will always be flats
- # IS better then too much duplicate code.
- flats = [(True, True)] * l
- for v in bezierVecs:
- v[PREV][Y] = v[NEXT][Y] = v[MID][Y]
-
-
- # remove middle points
- if l>2:
- done_nothing = False
-
- while not done_nothing and len(bezierVecs) > 2:
- done_nothing = True
- i = l-2
-
- while i > 0:
- #print i
- #print i, len(bezierVecs)
- if flats[i]==(True,True) and flats[i-1][RIGHT] and flats[i+1][LEFT]:
-
- if abs(bezierVecs[i][MID][Y] - bezierVecs[i-1][MID][Y]) < eul and abs(bezierVecs[i][MID][Y] - bezierVecs[i+1][MID][Y]) < eul:
- done_nothing = False
-
- del flats[i]
- del bezierVecs[i]
- icu.delBezier(i)
- TOT += 1
- l-=1
- i-=1
-
- # remove endpoints
- if extend == IpoCurve.ExtendTypes.CONST and len(bezierVecs) > 1:
- #print l, len(bezierVecs)
- # start
-
- while l > 2 and (flats[0][RIGHT] and flats[1][LEFT] and (abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul)):
- print "\tremoving 1 point from start of the curve"
- del flats[0]
- del bezierVecs[0]
- icu.delBezier(0)
- TOT += 1
- l-=1
-
-
- # End
- while l > 2 and flats[-2][RIGHT] and flats[-1][LEFT] and (abs(bezierVecs[-2][MID][Y] - bezierVecs[-1][MID][Y]) < eul):
- print "\tremoving 1 point from end of the curve", l
- del flats[l-1]
- del bezierVecs[l-1]
- icu.delBezier(l-1)
- TOT += 1
- l-=1
-
-
-
- if l==2:
- if isflat( bezierVecs[0] )[RIGHT] and isflat( bezierVecs[1] )[LEFT] and abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul:
- # remove the second point
- print "\tremoving 1 point from 2 point bez curve"
- # remove the second point
- del flats[1]
- del bezierVecs[1]
- icu.delBezier(1)
- TOT+=1
- l-=1
-
- # Change to linear for faster evaluation
- '''
- if l==1:
- print 'Linear'
- icu.interpolation = IpoCurve.InterpTypes.LINEAR
- '''
-
-
-
-
- if interp== IpoCurve.InterpTypes.CONST:
- print "Not yet supported"
-
- print 'total', TOT, TOTBEZ
- return TOT, TOTBEZ
-
-def main():
- ret = Draw.PupMenu('Clean Selected Objects Ipos%t|Object IPO%x1|Object Action%x2|%l|All IPOs (be careful!)%x3')
-
- sce = bpy.data.scenes.active
- ipos = []
-
- if ret == 3:
- ipos.extend(list(bpy.data.ipos))
- else:
- for ob in sce.objects.context:
- if ret == 1:
- ipo = ob.ipo
- if ipo:
- ipos.append(ipo)
-
- elif ret == 2:
- action = ob.action
- if action:
- ipos.extend([ipo for ipo in action.getAllChannelIpos().values() if ipo])
-
-
-
- if not ipos:
- Draw.PupMenu('Error%t|No ipos found')
- else:
- total_removed, total = clean_ipos(ipos)
- Draw.PupMenu('Done!%t|Removed ' + str(total_removed) + ' of ' + str(total) + ' points')
-
- Window.RedrawAll()
-
-
-if __name__ == '__main__':
- main()
diff --git a/release/scripts/image_2d_cutout.py b/release/scripts/image_2d_cutout.py
deleted file mode 100644
index 16d0805256b..00000000000
--- a/release/scripts/image_2d_cutout.py
+++ /dev/null
@@ -1,559 +0,0 @@
-#!BPY
-
-"""
-Name: '2D Cutout Image Importer'
-Blender: 249
-Group: 'Image'
-Tooltip: 'Batch UV Map images to Planes'
-"""
-
-__author__ = "Kevin Morgan (forTe)"
-__url__ = ("Home page, http://gamulabs.freepgs.com")
-__version__ = "1.2.1"
-__bpydoc__ = """\
-This Script will take an image and
-UV map it to a plane sharing the same width to height ratio as the image.
-Import options allow for the image to be a still or sequence type image
-<br><br>
-Imports can be single images or whole directories of images depending on the chosen
-option.
-"""
-
-####################################################
-#Copyright (C) 2008: Kevin Morgan
-####################################################
-#-------------GPL LICENSE BLOCK-------------
-#This program is free software: you can redistribute it and/or modify
-#it under the terms of the GNU General Public License as published by
-#the Free Software Foundation, either version 3 of the License, or
-#(at your option) any later version.
-#
-#This program is distributed in the hopes that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-#
-#You should have received a copy of the GNU General Public License
-#along with this program. If not, see <http://www.gnu.org/licenses>.
-####################################################
-####################################################
-#V1.0
-#Basic Functionality
-#Published June 28, 2007
-####################################################
-#V1.1
-#Added Support for enabling viewport transparency
-#Added more options to the UI for materials
-#Added Proportionality code (Pixels per unit)
-#Added GPL License Block
-#Published June 29, 2007
-####################################################
-#V1.2
-#Added Support for Copying Existing Materials
-#Import Images as Sequences
-#Refreshed GUI - now with more clutter :(
-#Miscellaneous and Housekeeping
-#Published June 16, 2008
-####################################################
-#V1.2.1
-#Added Extend Texture Mode option at request of a user
-#Published September 24, 2008
-####################################################
-
-import Blender
-from Blender import BGL, Draw, Image, Mesh, Material, Texture, Window
-from Blender.Mathutils import *
-import bpy
-
-# Global Constants
-DIR = 0
-SINGLE = 1
-CUROFFS = 0
-
-# GUI CONSTANTS
-NO_EVT = 0
-SINGLE_IMG = 1
-DIRECTORY_IMG = 2
-CLR_PATH = 3
-CHG_EXT = 4
-EXIT = 5
-DO_SCRIPT = 6
-
-VERSIONSTRING = '1.2.1'
-
-# Note the two parameter dicts could be combined, I just, liked them seperate...
-# GUI Buttons Dict
-GUIPARAMS = {
- 'Path': Draw.Create(''),
- 'ImageExt': Draw.Create(''),
- 'Seq': Draw.Create(0),
- 'PackImage': Draw.Create(0),
- 'PPU': Draw.Create(50),
- 'VPTransp': Draw.Create(1),
- 'XOff': Draw.Create(0.0),
- 'YOff': Draw.Create(0.0),
- 'ZOff': Draw.Create(0.0),
- 'CopyMat': Draw.Create(0),
- 'MatId': Draw.Create(0),
- 'MatCol': Draw.Create(1.0, 0.0, 0.0),
- 'Ref': Draw.Create(0.8),
- 'Spec': Draw.Create(0.5),
- 'Hard': Draw.Create(50),
- 'Alpha': Draw.Create(1.0),
- 'ZTransp': Draw.Create(1),
- 'Shadeless': Draw.Create(0),
- 'TexChan': Draw.Create(1),
- 'MPTCol': Draw.Create(1),
- 'MPTAlpha': Draw.Create(1),
- 'UseAlpha': Draw.Create(1),
- 'CalcAlpha': Draw.Create(0),
- 'ExtendMode': Draw.Create(0),
- 'AutoRefresh': Draw.Create(0),
- 'Cyclic': Draw.Create(0),
- 'Frames': Draw.Create(100),
- 'Offs': Draw.Create(0),
- 'StartFr': Draw.Create(1),
- 'RedrawImp': Draw.Create(0)
-}
-
-# Script Execution Paramaters
-PARAMS = {
- 'ImagePaths': [], # Path to images to import
- 'ImportType': SINGLE, # Import a Directory or a Single Image?
- 'ImageProp': Image.Sources.STILL, # What sources for the image, still or sequence
- 'PackImage': 0, # Pack the Image(s)?
- 'PPU': 20, # Pixels Per Blender Unit
- 'MakeTransp': 1, # Make face transparent in viewport
-
- 'NewMat': 1, # If true make a new material, otherwise duplicate an existing one, replacing appropriate attributes
- 'MaterialId': 0, # ID to take from the Materials list upon copy
- 'Materials': None, # Materials in Scene
- 'MatProps': {'Col': [1.0, 0.0, 0.0], 'Shadeless': 1, 'Ref': 0.5, 'Spec': 0.5, 'Hard': 200, 'Alpha': 1.0, 'ZTransp': 1},
-
- 'TexProps': {'UseAlpha': 1, 'CalcAlpha': 0, 'ExtendMode': 0}, # Texture Properties
- 'TexChannel': 0, # Texture Channel
- 'TexMapTo': {'Col': 1, 'Alpha': 1}, # Map to Col and/or Alpha
- 'SeqProps': {'AutoRefresh': 0, 'Cyclic': 0, 'Frames': 100, 'Offs': 0, 'StartFr': 1},
- 'ObOffset': Vector(1, 0, 0) # Offset by this vector upon creation for multifile import
-}
-
-# Get the Active Scene, of course
-scn = bpy.data.scenes.active
-
-##########################################
-# MAIN SCRIPT FUNCTIONS
-##########################################
-
-def imgImport(imgPath):
- global CUROFFS, PARAMS
- ######################################
- # Load the image
- ######################################
- try:
- img = Image.Load(imgPath)
- imgDimensions = img.getSize() # do this to ensure the data is available
- except:
- Blender.Draw.PupMenu('Error%t|Unsupported image format for "'+ imgPath.split('\\')[-1].split('/')[-1] +'"')
- return
-
- if PARAMS['PackImage']:
- img.pack()
- name = Blender.sys.makename(imgPath, strip = 1)
-
- ######################################
- # Construct the mesh
- ######################################
-
- me = Mesh.New(name)
-
- # Calculate Dimensions from Image Size
- dim = [float(i)/PARAMS['PPU'] for i in imgDimensions]
- v = [[dim[0], dim[1], 0], [-dim[0], dim[1], 0], [-dim[0], -dim[1], 0], [dim[0], -dim[1], 0]]
- me.verts.extend(v)
- me.faces.extend([0, 1, 2, 3])
-
- me.faces[0].image = img
- me.faces[0].uv = [Vector(1.0, 1.0), Vector(0.0, 1.0), Vector(0.0, 0.0), Vector(1.0, 0.0)]
-
- if PARAMS['MakeTransp']:
- me.faces[0].transp = Mesh.FaceTranspModes.ALPHA
-
- ######################################
- # Modify the Material
- ######################################
-
- mat = None
- if not PARAMS['NewMat']:
- mat = PARAMS['Materials'][PARAMS['MaterialId']].__copy__()
- mat.setName(name)
- else:
- mat = Material.New(name)
- properties = PARAMS['MatProps']
- mat.setRGBCol(properties['Col'])
- mat.setRef(properties['Ref'])
- mat.setSpec(properties['Spec'])
- mat.setHardness(properties['Hard'])
- mat.setAlpha(properties['Alpha'])
-
- if properties['Shadeless']:
- mat.mode |= Material.Modes.SHADELESS
- if properties['ZTransp']:
- mat.mode |= Material.Modes.ZTRANSP
-
- properties = PARAMS['TexProps']
-
- tex = Texture.New(name)
- tex.setType('Image')
- tex.setImage(img)
- if properties['UseAlpha']:
- tex.useAlpha = Texture.ImageFlags.USEALPHA
-
- if properties['CalcAlpha']:
- tex.calcAlpha = Texture.ImageFlags.CALCALPHA
-
- if properties['ExtendMode']:
- tex.setExtend('Extend')
-
- if PARAMS['ImageProp'] == Image.Sources.SEQUENCE:
- properties = PARAMS['SeqProps']
-
- img.source = PARAMS['ImageProp'] # Needs to be done here, otherwise an error with earlier getSize()
-
- tex.animStart = properties['StartFr']
- tex.animOffset = properties['Offs']
- tex.animFrames = properties['Frames']
- tex.autoRefresh = properties['AutoRefresh']
- tex.cyclic = properties['Cyclic']
-
- texMapSetters = Texture.TexCo.UV
-
- # PARAMS['TexMapTo']['Col'] (and alpha) will either be 0 or 1 because its from a toggle, otherwise this line doesn't work
- texChanSetters = Texture.MapTo.COL * PARAMS['TexMapTo']['Col'] | Texture.MapTo.ALPHA * PARAMS['TexMapTo']['Alpha']
-
- mat.setTexture(PARAMS['TexChannel'], tex, texMapSetters, texChanSetters)
- me.materials += [mat]
-
- ######################################
- # Object Construction
- ######################################
-
- ob = scn.objects.new(me, name)
- p = Vector(ob.getLocation()) # Should be the origin, but just to be safe, get it
- ob.setLocation((CUROFFS * PARAMS['ObOffset']) + p)
-
- return
-
-def translateParams():
- # Translates (or assigns for the most part) GUI values to those that can be read by the
- # Import Function
-
- global GUIPARAMS, PARAMS
-
- if GUIPARAMS['Seq'].val and PARAMS['ImportType'] != DIR:
- PARAMS['ImageProp'] = Image.Sources.SEQUENCE
-
- PARAMS['PackImage'] = GUIPARAMS['PackImage'].val
- PARAMS['PPU'] = GUIPARAMS['PPU'].val
- PARAMS['MakeTransp'] = GUIPARAMS['VPTransp'].val
- PARAMS['ObOffset'] = Vector(GUIPARAMS['XOff'].val, GUIPARAMS['YOff'].val, GUIPARAMS['ZOff'].val)
-
- PARAMS['NewMat'] = not GUIPARAMS['CopyMat'].val
- PARAMS['MaterialId'] = GUIPARAMS['MatId'].val
- PARAMS['MatProps']['Col'] = list(GUIPARAMS['MatCol'].val)
- PARAMS['MatProps']['Ref'] = GUIPARAMS['Ref'].val
- PARAMS['MatProps']['Spec'] = GUIPARAMS['Spec'].val
- PARAMS['MatProps']['Hard'] = GUIPARAMS['Hard'].val
- PARAMS['MatProps']['Alpha'] = GUIPARAMS['Alpha'].val
- PARAMS['MatProps']['ZTransp'] = GUIPARAMS['ZTransp'].val
- PARAMS['MatProps']['Shadeless'] = GUIPARAMS['Shadeless'].val
-
- PARAMS['TexChannel'] = GUIPARAMS['TexChan'].val - 1 #Channels are 0-9, but GUI shows 1-10
- PARAMS['TexProps']['UseAlpha'] = GUIPARAMS['UseAlpha'].val
- PARAMS['TexProps']['CalcAlpha'] = GUIPARAMS['CalcAlpha'].val
- PARAMS['TexProps']['ExtendMode'] = GUIPARAMS['ExtendMode'].val
- PARAMS['TexMapTo']['Col'] = GUIPARAMS['MPTCol'].val
- PARAMS['TexMapTo']['Alpha'] = GUIPARAMS['MPTAlpha'].val
-
- PARAMS['SeqProps']['AutoRefresh'] = GUIPARAMS['AutoRefresh'].val
- PARAMS['SeqProps']['Cyclic'] = GUIPARAMS['Cyclic'].val
- PARAMS['SeqProps']['Frames'] = GUIPARAMS['Frames'].val
- PARAMS['SeqProps']['Offs'] = GUIPARAMS['Offs'].val
- PARAMS['SeqProps']['StartFr'] = GUIPARAMS['StartFr'].val
- return
-
-def doScript():
- # Main script Function
- # Consists of choosing between 2 loops, one with a redraw, one without, see comments for why
-
- global CUROFFS
-
- translateParams()
-
- total = len(PARAMS['ImagePaths'])
- broken = 0
-
- if GUIPARAMS['RedrawImp'].val: # Reduces the need to compare on every go through the loop
- for i, path in enumerate(PARAMS['ImagePaths']):
- CUROFFS = i # Could be passed to the import Function, but I chose a global instead
- Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
- imgImport(path)
- Blender.Redraw()
- if Blender.Get('version') >= 246:
- if Window.TestBreak():
- broken = 1
- break
- else:
- for i, path in enumerate(PARAMS['ImagePaths']):
- CUROFFS = i
- Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
- imgImport(path)
- if Blender.Get('version') >= 246:
- if Window.TestBreak():
- broken = 1
- break
-
- if broken:
- Window.DrawProgressBar(1.0, "Script Execution Aborted")
- else:
- Window.DrawProgressBar(1.0, "Finished Importing")
-
- Blender.Redraw() # Force a refresh, since the user may have chosen to not refresh as they go along
-
- return
-
-##########################################
-# PATH SETTERS AND CHANGERS
-##########################################
-
-def setSinglePath(filename):
- global GUIPARAMS, PARAMS
- GUIPARAMS['Path'].val = filename
- PARAMS['ImagePaths'] = [filename]
- return
-
-def setDirPath(filename):
- global GUIPARAMS, PARAMS
-
- try:
- import os
- except:
- Draw.PupMenu('Full install of python required to be able to set Directory Paths')
- Draw.Exit()
- return
-
- path = os.path.dirname(filename) # Blender.sys.dirname fails on '/'
- GUIPARAMS['Path'].val = path
-
- ext_lower = GUIPARAMS['ImageExt'].val.lower()
- for f in os.listdir(path):
- if f.lower().endswith(ext_lower):
- PARAMS['ImagePaths'].append(os.path.join(path, f))
-
- return
-
-def changeExtension():
- global GUIPARAMS, PARAMS
-
- if PARAMS['ImportType'] == SINGLE:
- return
-
- try:
- import os
- except:
- Draw.PupMenu('Full install of python required to be able to set Directory Paths')
- Draw.Exit()
- return
-
- PARAMS['ImagePaths'] = []
-
- ext_lower = GUIPARAMS['ImageExt'].val.lower()
- for f in os.listdir(GUIPARAMS['Path'].val):
- if f.lower().endswith(ext_lower):
- PARAMS['ImagePaths'].append(os.path.join(GUIPARAMS['Path'].val, f))
-
- return
-
-##########################################
-# INTERFACE FUNCTIONS
-##########################################
-def compileMaterialList():
- # Pretty straight forward, just grabs the materials in the blend file and constructs
- # an appropriate string for use as a menu
-
- mats = [mat for mat in bpy.data.materials]
- PARAMS['Materials'] = mats
- title = 'Materials%t|'
- menStrs = [mat.name + '%x' + str(i) + '|' for i, mat in enumerate(mats)]
- return title + ''.join(menStrs)
-
-def event(evt, val):
- # Disabled, since Esc is often used from the file browser
- #if evt == Draw.ESCKEY:
- # Draw.Exit()
-
- return
-
-def bevent(evt):
- global GUIPARAMS, PARAMS
-
- if evt == NO_EVT:
- Draw.Redraw()
-
- elif evt == SINGLE_IMG:
- Window.FileSelector(setSinglePath, 'Image', Blender.sys.expandpath('//'))
- Draw.Redraw()
- PARAMS['ImportType'] = SINGLE
-
- elif evt == DIRECTORY_IMG:
- Window.FileSelector(setDirPath, 'Directory', Blender.sys.expandpath('//'))
- Draw.Redraw()
- PARAMS['ImportType'] = DIR
-
- elif evt == CLR_PATH:
- GUIPARAMS['Path'].val = ''
- PARAMS['ImagePaths'] = []
- GUIPARAMS['ImageExt'].val = ''
- Draw.Redraw()
-
- elif evt == CHG_EXT:
- changeExtension()
- Draw.Redraw()
-
- elif evt == EXIT:
- Draw.Exit()
-
- elif evt == DO_SCRIPT:
- doScript()
-
- else:
- print "ERROR: UNEXPECTED BUTTON EVENT"
-
- return
-
-# GUI Colors ######
-ScreenColor = [0.7, 0.7, 0.7]
-BackgroundColor = [0.8, 0.8, 0.8]
-TitleBG = [0.6, 0.6, 0.6]
-TitleCol = [1.0, 1.0, 1.0]
-ErrCol = [1.0, 0.0, 0.0]
-TextCol = [0.4, 0.4, 0.5]
-###################
-
-def GUI():
- global GUIPARAMS, PARAMS
-
- BGL.glClearColor(*(ScreenColor + [1.0]))
- BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
-
- minx = 5
- maxx = 500
- miny = 5
- maxy = 450
-
- lineheight = 24
- buPad = 5 # Generic Button Padding, most buttons should have 24-19 (or 5) px space around them
-
- lP = 5 # Left Padding
- rP = 5 # Right Padding
-
- # Draw Background Box
- BGL.glColor3f(*BackgroundColor)
- BGL.glRecti(minx, miny, maxx, maxy)
-
- # Draw Title
- BGL.glColor3f(*TitleBG)
- BGL.glRecti(minx, maxy - (lineheight), maxx, maxy)
- BGL.glColor3f(*TitleCol)
-
- title = "2D Cutout Image Importer v" + VERSIONSTRING
- BGL.glRasterPos2i(minx + lP, maxy - 15)
- Draw.Text(title, 'large')
-
- Draw.PushButton('Exit', EXIT, maxx-50-rP, maxy - lineheight + 2, 50, 19, "Exit Script")
-
- # Path Buttons
- if GUIPARAMS['Path'].val == '':
- Draw.PushButton('Single Image', SINGLE_IMG, minx + lP, maxy - (2*lineheight), 150, 19, "Select a Single Image to Import")
- Draw.PushButton('Directory', DIRECTORY_IMG, minx + lP + 150, maxy - (2*lineheight), 150, 19, "Select a Directory of Images to Import")
-
- else:
- Draw.PushButton('Clear', CLR_PATH, minx+lP, maxy - (2*lineheight), 50, 19, "Clear Path and Change Import Options")
-
- GUIPARAMS['Path'] = Draw.String('Path: ', NO_EVT, minx + lP, maxy - (3*lineheight), (maxx-minx-lP-rP), 19, GUIPARAMS['Path'].val, 399, 'Path to Import From')
- if PARAMS['ImportType'] == DIR:
- GUIPARAMS['ImageExt'] = Draw.String('Image Ext: ', CHG_EXT, minx + lP, maxy - (4*lineheight), 110, 19, GUIPARAMS['ImageExt'].val, 6, 'Image extension for batch directory importing (case insensitive)')
- GUIPARAMS['PackImage'] = Draw.Toggle('Pack', NO_EVT, maxx - rP - 50, maxy - (4*lineheight), 50, 19, GUIPARAMS['PackImage'].val, 'Pack Image(s) into .Blend File')
-
- # Geometry and Viewport Options
- BGL.glColor3f(*TextCol)
- BGL.glRecti(minx+lP, maxy - (5*lineheight), maxx-rP, maxy - (5*lineheight) + 1)
- BGL.glRasterPos2i(minx + lP, maxy-(5*lineheight) + 3)
- Draw.Text('Geometry and Display Options', 'small')
-
- GUIPARAMS['PPU'] = Draw.Slider('Pixels Per Unit: ', NO_EVT, minx + lP, maxy - (6*lineheight), (maxx-minx)/2 - lP, 19, GUIPARAMS['PPU'].val, 1, 5000, 0, 'Set the Number of Pixels Per Blender Unit to preserve Image Size Relations')
- GUIPARAMS['VPTransp'] = Draw.Toggle('Viewport Transparency', NO_EVT, minx + lP, maxy - (8*lineheight), (maxx-minx)/2 - lP, 2*lineheight - buPad, GUIPARAMS['VPTransp'].val, 'Display Alpha Transparency in the Viewport')
-
- GUIPARAMS['XOff'] = Draw.Slider('Offs X: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (6*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['XOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the X-Direction if Importing Multiple Images')
- GUIPARAMS['YOff'] = Draw.Slider('Offs Y: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (7*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['YOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Y-Direction if Importing Multiple Images')
- GUIPARAMS['ZOff'] = Draw.Slider('Offs Z: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (8*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['ZOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Z-Direction if Importing Multiple Images')
-
- # Material and Texture Options
- BGL.glColor3f(*TextCol)
- BGL.glRecti(minx+lP, maxy - (9*lineheight), maxx-rP, maxy - (9*lineheight) + 1)
- BGL.glRasterPos2i(minx + lP, maxy-(9*lineheight) + 3)
- Draw.Text('Material and Texture Options', 'small')
-
- half = (maxx-minx-lP-rP)/2
- GUIPARAMS['CopyMat'] = Draw.Toggle('Copy Existing Material', NO_EVT, minx + lP, maxy-(10*lineheight), half, 19, GUIPARAMS['CopyMat'].val, 'Copy an Existing Material')
- if GUIPARAMS['CopyMat'].val:
- menStr = compileMaterialList()
- GUIPARAMS['MatId'] = Draw.Menu(menStr, NO_EVT, minx + lP, maxy - (11*lineheight), half, 19, GUIPARAMS['MatId'].val, 'Material to Copy Settings From')
- else:
- GUIPARAMS['MatCol'] = Draw.ColorPicker(NO_EVT, minx+lP, maxy - (13*lineheight), 40, (3*lineheight) - buPad, GUIPARAMS['MatCol'].val, 'Color of Newly Created Material')
- GUIPARAMS['Ref'] = Draw.Slider('Ref: ', NO_EVT, minx +lP+45, maxy - (11*lineheight), half-45, 19, GUIPARAMS['Ref'].val, 0.0, 1.0, 0, 'Set the Ref Value for Created Materials')
- GUIPARAMS['Spec'] = Draw.Slider('Spec: ', NO_EVT, minx +lP+45, maxy - (12*lineheight), half-45, 19, GUIPARAMS['Spec'].val, 0.0, 2.0, 0, 'Set the Spec Value for Created Materials')
- GUIPARAMS['Hard'] = Draw.Slider('Hard: ', NO_EVT, minx +lP+45, maxy - (13*lineheight), half-45, 19, GUIPARAMS['Hard'].val, 1, 500, 0, 'Set the Hardness Value for Created Materials')
- GUIPARAMS['Alpha'] = Draw.Slider('A: ', NO_EVT, minx +lP, maxy - (14*lineheight), half, 19, GUIPARAMS['Alpha'].val, 0.0, 1.0, 0, 'Set the Alpha Value for Created Materials')
-
- GUIPARAMS['ZTransp'] = Draw.Toggle('ZTransparency', NO_EVT, minx + lP, maxy - (15*lineheight), half, 19, GUIPARAMS['ZTransp'].val, 'Enable ZTransparency')
- GUIPARAMS['Shadeless'] = Draw.Toggle('Shadeless', NO_EVT, minx + lP, maxy - (16*lineheight), half, 19, GUIPARAMS['Shadeless'].val, 'Enable Shadeless')
-
- GUIPARAMS['TexChan'] = Draw.Number('Texture Channel: ', NO_EVT, minx + lP+ half + buPad, maxy - (10*lineheight), half-rP, 19, GUIPARAMS['TexChan'].val, 1, 10, 'Texture Channel for Image Texture')
-
- GUIPARAMS['MPTCol'] = Draw.Toggle('Color', NO_EVT, minx + lP + half + buPad, maxy - (11*lineheight), half/2, 19, GUIPARAMS['MPTCol'].val, 'Map To Color Channel')
- GUIPARAMS['MPTAlpha'] = Draw.Toggle('Alpha', NO_EVT, minx + lP + int((1.5)*half) + buPad, maxy - (11*lineheight), half/2 - rP, 19, GUIPARAMS['MPTAlpha'].val, 'Map To Alpha Channel')
-
- third = int((maxx-minx-lP-rP)/6)
- GUIPARAMS['UseAlpha'] = Draw.Toggle('Use Alpha', NO_EVT, minx + lP + half + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['UseAlpha'].val, "Use the Images' Alpha Values")
- GUIPARAMS['CalcAlpha'] = Draw.Toggle('Calc Alpha', NO_EVT, minx + lP + half + third + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['CalcAlpha'].val, "Calculate Images' Alpha Values")
- GUIPARAMS['ExtendMode'] = Draw.Toggle('Extend', NO_EVT, minx+lP+half+third+third+buPad, maxy - (12*lineheight), third-3, 19, GUIPARAMS['ExtendMode'].val, "Use Extend texture mode. If deselected, Repeat is used")
- GUIPARAMS['Seq'] = Draw.Toggle('Sequence', NO_EVT, minx + lP + half + buPad, maxy - (13*lineheight), half-rP, 19, GUIPARAMS['Seq'].val, 'Set the Image(s) to use a Sequence instead of a Still')
-
- if GUIPARAMS['Seq'].val and not PARAMS['ImportType'] == DIR:
- GUIPARAMS['AutoRefresh'] = Draw.Toggle('Auto Refresh', NO_EVT, minx + lP + half + buPad, maxy - (14*lineheight), half/2, 19, GUIPARAMS['AutoRefresh'].val, 'Use Auto Refresh')
- GUIPARAMS['Cyclic'] = Draw.Toggle('Cyclic', NO_EVT, minx + lP + half + buPad + half/2, maxy - (14*lineheight), half/2 - rP, 19, GUIPARAMS['Cyclic'].val, 'Repeat Frames Cyclically`')
-
- GUIPARAMS['Frames'] = Draw.Number('Frames: ', NO_EVT, minx +lP + half + buPad, maxy - (15*lineheight), half - rP, 19, GUIPARAMS['Frames'].val, 1, 30000, 'Sets the Number of Images of a Movie to Use')
- GUIPARAMS['Offs'] = Draw.Number('Offs: ', NO_EVT, minx +lP + half + buPad, maxy - (16*lineheight), half/2, 19, GUIPARAMS['Offs'].val, -30000, 30000, 'Offsets the Number of the Frame to use in the Animation')
- GUIPARAMS['StartFr'] = Draw.Number('StartFr: ', NO_EVT, minx +lP + half + buPad + half/2, maxy - (16*lineheight), half/2 - rP, 19, GUIPARAMS['StartFr'].val, 1, 30000, 'Sets the Global Starting Frame of the Movie')
- elif GUIPARAMS['Seq'].val and PARAMS['ImportType'] == DIR:
- BGL.glColor3f(*ErrCol)
- BGL.glRasterPos2i(minx + lP + half + buPad + 7, maxy-(14 * lineheight) + 5)
- Draw.Text('Sequence only available for Single Image Import', 'small')
-
- # Import Options
- BGL.glColor3f(*TextCol)
- BGL.glRecti(minx+lP, maxy - (17*lineheight), maxx-rP, maxy - (17*lineheight) + 1)
- BGL.glRasterPos2i(minx + lP, maxy-(17*lineheight) + 3)
- Draw.Text('Import', 'small')
-
- if GUIPARAMS['Path'].val and GUIPARAMS['ImageExt'].val or GUIPARAMS['Path'].val and PARAMS['ImportType'] == SINGLE:
- Draw.PushButton('Import', DO_SCRIPT, minx + lP, maxy - (18*lineheight), 75, 19, "Import Image(s)")
- else:
- BGL.glColor3f(*ErrCol)
- BGL.glRasterPos2i(minx+lP, maxy - (18*lineheight) + 5)
- Draw.Text('A path and image type must be specified to import images')
-
- GUIPARAMS['RedrawImp'] = Draw.Toggle('Redraw During Import', NO_EVT, maxx - rP - 150, maxy - (18*lineheight), 150, 19, GUIPARAMS['RedrawImp'].val, 'Redraw the View as Images Import')
-
-Draw.Register(GUI, event, bevent) \ No newline at end of file
diff --git a/release/scripts/object_active_to_other.py b/release/scripts/object_active_to_other.py
deleted file mode 100644
index 131d1f63d74..00000000000
--- a/release/scripts/object_active_to_other.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!BPY
-"""
-Name: 'Copy Active to Selected'
-Blender: 249
-Group: 'Object'
-Tooltip: 'For every selected object, copy the active to their loc/size/rot'
-"""
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# Script copyright (C) Campbell Barton
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-# --------------------------------------------------------------------------
-
-
-from Blender import Window, sys, Draw
-import bpy
-
-def my_object_util(sce):
- ob_act = sce.objects.active
-
- if not ob_act:
- Draw.PupMenu('Error%t|No active object selected')
- return
-
- mats = [ob.matrixWorld for ob in sce.objects.context if ob != ob_act]
-
- for m in mats:
- ob_copy = ob_act.copy()
- sce.objects.link(ob_copy)
- ob_copy.setMatrix(m)
- ob_copy.Layers = ob.Layers
-
-
-def main():
- sce = bpy.data.scenes.active
-
- Window.WaitCursor(1)
- my_object_util(sce)
- Window.WaitCursor(0)
-
-if __name__ == '__main__':
- main()
diff --git a/release/scripts/scripttemplate_gamelogic_module.py b/release/scripts/scripttemplate_gamelogic_module.py
deleted file mode 100644
index 2ef4950917b..00000000000
--- a/release/scripts/scripttemplate_gamelogic_module.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!BPY
-"""
-Name: 'GameLogic Module'
-Blender: 249
-Group: 'ScriptTemplate'
-Tooltip: 'Basic template for new game logic modules'
-"""
-
-from Blender import Window
-import bpy
-
-script_data = \
-'''
-# This module can be accessed by a python controller with
-# its execution method set to 'Module'
-# * Set the module string to "gamelogic_module.main" (without quotes)
-# * When renaming the script it MUST have a .py extension
-# * External text modules are supported as long as they are at
-# the same location as the blendfile or one of its libraries.
-
-import GameLogic
-
-# variables defined here will only be set once when the
-# module is first imported. Set object spesific vars
-# inside the function if you intend to use the module
-# with multiple objects.
-
-def main(cont):
- own = cont.owner
-
- sens = cont.sensors['mySensor']
- actu = cont.actuators['myActuator']
-
- if sens.positive:
- cont.activate(actu)
- else:
- cont.deactivate(actu)
-
-# dont call main(GameLogic.getCurrentController()), the py controller will
-'''
-
-new_text = bpy.data.texts.new('gamelogic_module.py')
-new_text.write(script_data)
-bpy.data.texts.active = new_text
-Window.RedrawAll()
diff --git a/release/scripts/textplugin_convert_ge.py b/release/scripts/textplugin_convert_ge.py
deleted file mode 100644
index 21e065bcfd7..00000000000
--- a/release/scripts/textplugin_convert_ge.py
+++ /dev/null
@@ -1,863 +0,0 @@
-#!BPY
-"""
-Name: 'Convert BGE 2.49'
-Blender: 246
-Group: 'TextPlugin'
-Shortcut: ''
-Tooltip: 'Attemps to update deprecated usage of game engine API.'
-"""
-
-#
-# Copyright 2009 Alex Fraser <alex@phatcore.com>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-#
-# This script updates game engine scripts that were designed for pre-2.49
-# versions of Blender to run with the new API. Deprecated function calls are
-# listed in attributeRenameDict. This script searches for instances of the keys
-# in a target script and re-writes them.
-#
-# Some deprecated functions are complicated to re-write. The most common
-# conversions have been implemented, but some have not. Running this will reduce
-# the number of deprecation warnings in your scripts, but may not eliminate them
-# entirely.
-#
-# NOTE: The conversion is not guaranteed to be perfect. It is strongly
-# recommended that you review all changes after running this script.
-#
-# TODO: The following attributes are either ambiguous or need special processing
-# to handle parameters. Deprecated attributes that map to multiple target
-# attributes will require a refactor of the main conversion loop in the
-# convert248to249 function: currently, it doesn't allow any conversion to
-# advance the row index by more than one.
-#
-# getLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
-# Conflicts with KX_GameObject.
-# Maps to multiple attributes.
-# setLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
-# Conflicts with KX_GameObject.
-# Maps to multiple attributes.
-# getAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
-# Conflicts with KX_GameObject.
-# Maps to multiple attributes.
-# setAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
-# Conflicts with KX_GameObject.
-# Maps to multiple attributes.
-# setAction (BL_ShapeActionActuator, BL_ActionActuator)
-# `reset' argument has no conversion target.
-# set (KX_VisibilityActuator, KX_IpoActuator)
-# Different numbers of arguments.
-# Arguments map to multiple attributes.
-# getIndex (SCA_JoystickSensor)
-# Incompatible values: Old = 1-based index; new = 0-based.
-# getMesh (KX_SCA_ReplaceMeshActuator)
-# Return types differ. Need to call object.name.
-# getObject (KX_SCA_AddObjectActuator, KX_CameraActuator,
-# KX_TrackToActuator, KX_ParentActuator)
-# Default return type differs between classes.
-# setIndex (SCA_JoystickSensor)
-# Incompatible values: Old = 1-based index; new = 0-based.
-# setObject (KX_SCA_AddObjectActuator, KX_CameraActuator,
-# KX_TrackToActuator, KX_ParentActuator)
-# Incompatible types: Old = KX_GameObject or String; new =
-# KX_GameObject.
-# setOperation (KX_SCA_DynamicActuator, KX_StateActuator)
-# Ambiguous: different target names.
-# getDRot (KX_ObjectActuator)
-# Maps to multiple attributes.
-# setDRot (KX_ObjectActuator)
-# Arguments map to multiple attributes.
-# getDLoc (KX_ObjectActuator)
-# Maps to multiple attributes.
-# setDLoc (KX_ObjectActuator)
-# Arguments map to multiple attributes.
-# getTorque (KX_ObjectActuator)
-# Maps to multiple attributes.
-# setTorque (KX_ObjectActuator)
-# Arguments map to multiple attributes.
-# getForce (KX_ObjectActuator)
-# Maps to multiple attributes.
-# setForce (KX_ObjectActuator)
-# Arguments map to multiple attributes.
-# position (KX_GameObject)
-# Conflicts with KX_SoundActuator.
-# orientation (KX_GameObject)
-# Conflicts with KX_SoundActuator.
-#
-
-import string
-import re
-
-COMMENTCHAR = '#'
-
-class ParseError(Exception): pass
-class ConversionError(Exception): pass
-
-def findBalancedParens(lines, row, col, openChar = '(', closeChar = ')'):
- """Finds a balanced pair of parentheses, searching from lines[row][col].
- The opening parenthesis must be on the starting line.
-
- Returns two tuples containing the row and column of the opening paren, and
- the row and column of the matching paren.
-
- Throws a ParseError if the first character is not openChar, or if a matching
- paren cannot be found."""
-
- #
- # Find the opening coordinates.
- #
- oRow = row
- oCol = col
- line = lines[oRow]
- while oCol < len(line):
- if line[oCol] == openChar:
- break
- elif line[oCol] == COMMENTCHAR:
- break
- oCol = oCol + 1
-
- if oCol >= len(line) or line[oCol] != openChar or not re.match(r'^\s*$', line[col:oCol]):
- raise ParseError, "Can't find opening parenthesis. '%s'" % openChar
-
- #
- # Find the closing coordinates.
- #
- eRow = oRow
- eCol = oCol + 1
- level = 1
- while eRow < len(lines) and level > 0:
- line = lines[eRow]
- while eCol < len(line) and level > 0:
- c = line[eCol]
- if c == openChar:
- # Found a nested paren.
- level = level + 1
- elif c == closeChar:
- # Exiting one level of nesting.
- level = level - 1
- if level == 0:
- # Back to top level!
- return (oRow, oCol), (eRow, eCol)
- elif c == COMMENTCHAR:
- # Comment. Skip the rest of the line.
- break
- eCol = eCol + 1
- eRow = eRow + 1
- eCol = 0
- raise ParseError, "Couldn't find closing parenthesis."
-
-def findLastAssignment(lines, row, attrName):
- """Finds the most recent assignment of `attrName' before `row'. Returns
- everything after the '=' sign or None, if there was no match."""
- contRegex = re.compile(r'[^#]*?' + # Don't search in comments.
- attrName +
- r'\s*=\s*(.*)') # Assignment
-
- cRow = row - 1
- while cRow >= 0:
- match = contRegex.search(lines[cRow])
- if match:
- return match.group(1)
- cRow = cRow - 1
- return None
-
-def replaceSubstr(s, start, end, newSubStr):
- """Replace the contents of `s' between `start' and `end' with
- `newSubStr'."""
- return s[:start] + newSubStr + s[end:]
-
-def replaceNextParens(lines, row, colStart, newOpenChar, newCloseChar,
- oldOpenChar = '(', oldCloseChar = ')'):
- """Replace the next set of parentheses with different characters. The
- opening parenthesis must be located on line `row', and on or after
- `colStart'. The closing parenthesis may be on the same line or any following
- line. The strings are edited in-place.
-
- Throws a ParseError if the set of parentheses can't be found. In this case,
- the strings in `lines' will be untouched."""
- try:
- pOpen, pClose = findBalancedParens(lines, row, colStart, oldOpenChar,
- oldCloseChar)
- except ParseError:
- raise
-
- # Replacement may change string length. Replace closing paren first.
- r, c = pClose
- lines[r] = replaceSubstr(lines[r], c, c + 1, newCloseChar)
- # Replace opening paren.
- r, c = pOpen
- lines[r] = replaceSubstr(lines[r], c, c + 1, newOpenChar)
-
-def replaceSimpleGetter(lines, row, colStart, colEnd, newName):
- """Replace a call to a simple getter function with a reference to a
- property, e.g. foo.getBar() -> foo.bar
-
- The function identifier being replaced must be on line `row' and
- between `colStart' and `colEnd'. The opening parenthesis must follow
- immediately (whitespace is allowed). The closing parenthesis may be on the
- same or following lines.
-
- Throws a ConversionError if the parentheses can't be found. In this case
- the content of `lines' will be untouched."""
- try:
- replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '')
- except ParseError:
- raise ConversionError, ("Deprecated function reference.")
-
- lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
-
-def replaceSimpleSetter(lines, row, colStart, colEnd, newName):
- """Replace a call to a simple setter function with a reference to a
- property, e.g. foo.setBar(baz) -> foo.bar = baz
-
- The function identifier being replaced must be on line `row' and
- between `colStart' and `colEnd'. The opening parenthesis must follow
- immediately (whitespace is allowed). The closing parenthesis may be on the
- same or following lines.
-
- Throws a ConversionError if the parentheses can't be found. In this case
- the content of `lines' will be untouched."""
- try:
- replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '')
- except ParseError:
- raise ConversionError, ("Deprecated function reference.")
-
- lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ')
-
-def replaceArgsWithListSetter(lines, row, colStart, colEnd, newName):
- """Replace a call to a multi-agument setter function with a reference to a
- list property, e.g. foo.setBar(baz, bazZ) -> foo.bar = [baz, bazZ]
-
- The function identifier being replaced must be on line `row' and
- between `colStart' and `colEnd'. The opening parenthesis must follow
- immediately (whitespace is allowed). The closing parenthesis may be on the
- same or following lines.
-
- Throws a ConversionError if the parentheses can't be found. In this case
- the content of `lines' will be untouched."""
- try:
- replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']')
- except ParseError:
- raise ConversionError, ("Deprecated function reference.")
-
- lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ')
-
-
-def replaceKeyedGetter(lines, row, colStart, colEnd, newName):
- """Replace a call to a keyed getter function with a reference to a
- property, e.g. foo.getBar(baz) -> foo.bar[baz]
-
- The function identifier being replaced must be on line `row' and
- between `colStart' and `colEnd'. The opening parenthesis must follow
- immediately (whitespace is allowed). The closing parenthesis may be on the
- same or following lines.
-
- Throws a ConversionError if the parentheses can't be found. In this case
- the content of `lines' will be untouched."""
- try:
- replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']')
- except ParseError:
- raise ConversionError, ("Deprecated function reference.")
-
- lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
-
-def replaceGetXYPosition(lines, row, colStart, colEnd, axis):
- '''SCA_MouseSensor.getXPosition; SCA_MouseSensor.getYPosition.
- This is like a keyed getter, but the key is embedded in the attribute
- name.
-
- Throws a ConversionError if the parentheses can't be found. In this case
- the content of `lines' will be untouched.'''
- try:
- (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines,
- row, colEnd)
- except ParseError:
- raise ConversionError, "Deprecated function reference."
- if closeRow != row:
- raise ConversionError, "Can't modify multiple lines."
-
- lines[row] = replaceSubstr(lines[row], openCol, closeCol + 1,
- "[%s]" % axis)
-
- lines[row] = replaceSubstr(lines[row], colStart, colEnd, 'position')
-
-def replaceRename(lines, row, colStart, colEnd, newName):
- """Replace an identifier with another, e.g.
- foo.getBar() -> foo.getBaz()
- foo.bar -> foo.baz
-
- The identifier being replaced must be on line `row' and between `colStart'
- and `colEnd'."""
- lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
-
-def replaceAddActiveActuator(lines, row, colStart, colEnd, closure):
- '''Extra work needs to be done here to find out the name of the controller,
- and whether the actuator should be activated or deactivated.
-
- Throws a ConversionError if the actuator, controller or condition can't be
- found. In this case the content of `lines' will be untouched.'''
- try:
- (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines, row, colEnd)
- except ParseError:
- ConversionError, "Can't find arguments."
-
- if closeRow != openRow:
- raise ConversionError, ("Can't perform conversion: arguments span multiple lines.")
-
- args = lines[row][openCol + 1:closeCol]
- match = re.search(r'([a-zA-Z_]\w*)' # Actuator identifier
- r',\s*'
- r'([0-9a-zA-Z_]\w*)', # Condition (boolean)
- args)
- if not match:
- raise ConversionError, "Can't find arguments."
-
- actuator = match.group(1)
- condition = match.group(2)
- controller = None
-
- assn = findLastAssignment(lines, row, actuator)
- if assn:
- match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
- r'\s*\.\s*' # Dot
- r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
- assn)
- if match:
- controller = match.group(1)
-
- if not controller:
- raise ConversionError, "Can't find actuator's controller."
-
- gameLogicStart = lines[row].rfind("GameLogic", 0, colStart)
- if gameLogicStart < 0:
- raise ConversionError, "Can't find GameLogic identifier."
-
- newExpr = None
- if condition in ['1', 'True']:
- newExpr = "%s.activate(%s)" % (controller, actuator)
- elif condition in ['0', 'False']:
- newExpr = "%s.deactivate(%s)" % (controller, actuator)
- else:
- newExpr = "(lambda: %s and (%s.activate(%s) or True) or %s.deactivate(%s))()" % (
- condition, controller, actuator, controller, actuator)
- lines[row] = replaceSubstr(lines[row], gameLogicStart, closeCol + 1, newExpr)
-
-def getObject(line, attributeStart):
- '''Get the object that an attribute belongs to. `attributeStart' is the
- index of the first character of the attribute name in the string `line'.
- Returns: the identifier preceding `attributeStart', or None if one can't be
- found.'''
- match = re.search(r'([a-zA-Z_]\w*)\s*\.\s*$', line[0:attributeStart])
- if not match:
- return None
- return match.group(1)
-
-def replaceGetActuator(lines, row, colStart, colEnd, closure):
- '''getActuator is ambiguous: it could belong to SCA_IController or
- SCA_ActuatorSensor. Try to resolve and then convert.
-
- Raises a ConversionError if the parentheses can't be found, or if the
- ambiguity can't be resolved.'''
- # Get the name of the object this attribute is attached to.
- obName = getObject(lines[row], colStart)
- if obName:
- # Try to find out whether the object is a controller.
- assn = findLastAssignment(lines, row, obName)
- if assn and re.search(r'GameLogic\s*\.\s*getCurrentController', assn):
- # It is (probably) a controller!
- replaceKeyedGetter(lines, row, colStart, colEnd, 'actuators')
- return
-
- raise ConversionError, "Ambiguous: addActiveActuator -> actuators[key] (SCA_IController) or actuator (SCA_ActuatorSensor)."
-
-def replaceSetOrientation(lines, row, colStart, colEnd, closure):
- '''setOrientation is ambiguous: it could belong to KX_SoundActuator or
- KX_GameObject. Try to resolve and then convert. If the type can't be
- determined, it is assumed to be a KX_GameObject. Currently, only the
- conversion for KX_GameObject is implemented.
-
- Raises a ConversionError if the parentheses can't be found, or if the
- object is found to be a KX_SoundActuator.'''
- # Get the name of the object this attribute is attached to.
- obName = getObject(lines[row], colStart)
- if obName:
- # Try to find out whether the object is an actuator.
- assn = findLastAssignment(lines, row, obName)
- if assn:
- match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
- r'\s*\.\s*' # Dot
- r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
- assn)
- if match:
- # It's probably a KX_SoundActuator.
- raise ConversionError, "Not implemented: Can't convert arguments to matrix."
-
- # It's probably a KX_GameObject.
- replaceSimpleSetter(lines, row, colStart, colEnd, 'localOrientation')
-
-def replaceSetPosition(lines, row, colStart, colEnd, closure):
- '''setPosition is ambiguous: it could belong to KX_SoundActuator or
- KX_GameObject. Try to resolve and then convert. If the type can't be
- determined, it is assumed to be a KX_GameObject.
-
- Raises a ConversionError if the parentheses can't be found.'''
- # Get the name of the object this attribute is attached to.
- obName = getObject(lines[row], colStart)
- if obName:
- # Try to find out whether the object is an actuator.
- assn = findLastAssignment(lines, row, obName)
- if assn:
- match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
- r'\s*\.\s*' # Dot
- r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
- assn)
- if match:
- # It's probably a KX_SoundActuator.
- replaceSimpleSetter(lines, row, colStart, colEnd, 'position')
-
- # It's probably a KX_GameObject.
- replaceSimpleSetter(lines, row, colStart, colEnd, 'localPosition')
-
-def replaceSplitProperty(lines, row, colStart, colEnd, (newGetter, newSetter)):
- '''Some property attributes behave differently when being written to or read
- from. Try to determine the operation, and replace accordingly. E.G.
- o.position = foo -> o.localPosition = foo # set
- foo = o.position -> foo = o.worldPosition # get
-
- This implementation can not handle cases where the object is returned from
- a function, e.g.
- foo = bar.getObject().position # Error!
-
- Raises a ConversionError if the operation can't be determined, or if the
- object is returned from a function.'''
- assnRegex = re.compile(r'(=\s*)?' # Getter
- r'[a-zA-Z_]\w*' # Object identifier
- r'\.([a-zA-Z_][a-zA-Z0-9_.]*)+' # Trailing attributes
- r'(\s*=)?') # Setter
- match = assnRegex.search(lines[row])
-
- if not match:
- raise ConversionError, "Can't determine operation (getting or setting)."
-
- setting = False
- getting = False
- if match.group(1):
- getting = True
- if match.group(3):
- setting = True
- if (getting and setting) or ((not getting) and (not setting)):
- raise ConversionError, "Can't determine operation (getting or setting)."
-
- if getting:
- replaceRename(lines, row, colStart, colEnd, newGetter)
- else:
- replaceRename(lines, row, colStart, colEnd, newSetter)
-
-def notImplemented(lines, row, colStart, colEnd, classNames):
- message = "Conversion not implemented. See documentation for " +\
- string.join(classNames, ', ')
- raise ConversionError, message
-
-#
-# Deprecated attribute information. The format is:
-# deprecatedAttributeName: (conversionFunction, closure)
-# Usually the closure will be the name of the superceding attribute.
-#
-# Since each deprecated attribute can appear in this dictionary only once, it is
-# the conversion function's responsibility to resolve ambiguity.
-#
-attributeRenameDict = {
- # Special cases
- 'addActiveActuator': (replaceAddActiveActuator, None), #
- 'getActuator': (replaceGetActuator, None), # SCA_IController, SCA_ActuatorSensor
- 'getXPosition': (replaceGetXYPosition, '0'), # SCA_MouseSensor
- 'getYPosition': (replaceGetXYPosition, '1'), # SCA_MouseSensor
- 'setOrientation': (replaceSetOrientation, None), # KX_GameObject, KX_SoundActuator
- 'setPosition': (replaceSetPosition, None), # KX_GameObject, KX_SoundActuator
-
- # Keyed getters/setters
- 'getSensor': (replaceKeyedGetter, 'sensors'), # SCA_IController
-
- # Multi-arg -> List setter
- 'setAxis': (replaceArgsWithListSetter, 'axis'), # SCA_JoystickSensor
- 'setForceLimitX': (replaceArgsWithListSetter, 'forceLimitX'), # KX_ObjectActuator
- 'setForceLimitY': (replaceArgsWithListSetter, 'forceLimitY'), # KX_ObjectActuator
- 'setForceLimitZ': (replaceArgsWithListSetter, 'forceLimitZ'), # KX_ObjectActuator
- 'setHat': (replaceArgsWithListSetter, 'hat'), # SCA_JoystickSensor
- 'setPID': (replaceArgsWithListSetter, 'pid'), # KX_ObjectActuator
- 'setVelocity': (replaceArgsWithListSetter, 'velocity'), # KX_SoundActuator
-
- # Straight rename
- 'getButtonValue': (replaceRename, 'getButtonActiveList'), # SCA_JoystickSensor
-
- # Split properties
- 'scaling': (replaceSplitProperty, ('worldScaling', 'localScaling')), # KX_GameObject
-
- # Simple getters/setters
- 'getSensors': (replaceSimpleGetter, 'sensors'), # SCA_IController
- 'getActuators': (replaceSimpleGetter, 'actuators'), # SCA_IController
- 'enableViewport': (replaceSimpleSetter, 'useViewport'), # KX_Camera
- 'getAction': (replaceSimpleGetter, 'action'), # BL_ShapeActionActuator, BL_ActionActuator
- 'getAxis': (replaceSimpleGetter, 'axis'), # SCA_JoystickSensor
- 'getAxisValue': (replaceSimpleGetter, 'axisValues'), # SCA_JoystickSensor
- 'getBlendin': (replaceSimpleGetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator
- 'getBodies': (replaceSimpleGetter, 'bodies'), # KX_NetworkMessageSensor
- 'getButton': (replaceSimpleGetter, 'button'), # SCA_JoystickSensor
- 'getCamera': (replaceSimpleGetter, 'camera'), # KX_SceneActuator
- 'getConeOrigin': (replaceSimpleGetter, 'coneOrigin'), # KX_RadarSensor
- 'getConeTarget': (replaceSimpleGetter, 'coneTarget'), # KX_RadarSensor
- 'getContinue': (replaceSimpleGetter, 'useContinue'), # BL_ActionActuator
- 'getCurrentlyPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor
- 'getDamping': (replaceSimpleGetter, 'damping'), # KX_ObjectActuator
- 'getDelay': (replaceSimpleGetter, 'delay'), # SCA_DelaySensor
- 'getDistribution': (replaceSimpleGetter, 'distribution'), # SCA_RandomActuator
- 'getDuration': (replaceSimpleGetter, 'duration'), # SCA_DelaySensor
- 'getEnd': (replaceSimpleGetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
- 'getExecutePriority': (replaceSimpleGetter, 'executePriority'), # SCA_ILogicBrick
- 'getFile': (replaceSimpleGetter, 'fileName'), # KX_GameActuator
- 'getFilename': (replaceSimpleGetter, 'fileName'), # KX_SoundActuator
- 'getForceIpoActsLocal': (replaceSimpleGetter, 'useIpoLocal'), # KX_IpoActuator
- 'getForceLimitX': (replaceSimpleGetter, 'forceLimitX'), # KX_ObjectActuator
- 'getForceLimitY': (replaceSimpleGetter, 'forceLimitY'), # KX_ObjectActuator
- 'getForceLimitZ': (replaceSimpleGetter, 'forceLimitZ'), # KX_ObjectActuator
- 'getFrame': (replaceSimpleGetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator
- 'getFrameMessageCount': (replaceSimpleGetter, 'frameMessageCount'), # KX_NetworkMessageSensor
- 'getFrameProperty': (replaceSimpleGetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator
- 'getFrequency': (replaceSimpleGetter, 'frequency'), # SCA_ISensor
- 'getGain': (replaceSimpleGetter, 'volume'), # KX_SoundActuator, KX_CDActuator
- 'getHat': (replaceSimpleGetter, 'hat'), # SCA_JoystickSensor
- 'getHeight': (replaceSimpleGetter, 'height'), # KX_CameraActuator
- 'getHitNormal': (replaceSimpleGetter, 'hitNormal'), # KX_MouseFocusSensor, KX_RaySensor
- 'getHitObject': (replaceSimpleGetter, 'hitObject'), # KX_MouseFocusSensor, KX_RaySensor, KX_TouchSensor
- 'getHitObjectList': (replaceSimpleGetter, 'hitObjectList'), # KX_TouchSensor
- 'getHitPosition': (replaceSimpleGetter, 'hitPosition'), # KX_MouseFocusSensor, KX_RaySensor
- 'getHold1': (replaceSimpleGetter, 'hold1'), # SCA_KeyboardSensor
- 'getHold2': (replaceSimpleGetter, 'hold2'), # SCA_KeyboardSensor
- 'getInvert': (replaceSimpleGetter, 'invert'), # SCA_ISensor
- 'getIpoAdd': (replaceSimpleGetter, 'useIpoAdd'), # KX_IpoActuator
- 'getIpoAsForce': (replaceSimpleGetter, 'useIpoAsForce'), # KX_IpoActuator
- 'getKey': (replaceSimpleGetter, 'key'), # SCA_KeyboardSensor
- 'getLastCreatedObject': (replaceSimpleGetter, 'objectLastCreated'), # KX_SCA_AddObjectActuator
- 'getLevel': (replaceSimpleGetter, 'level'), # SCA_ISensor
- 'getLightList': (replaceSimpleGetter, 'lights'), # KX_Scene
- 'getLooping': (replaceSimpleGetter, 'looping'), # KX_SoundActuator
- 'getMass': (replaceSimpleGetter, 'mass'), # KX_GameObject
- 'getMax': (replaceSimpleGetter, 'max'), # KX_CameraActuator
- 'getMin': (replaceSimpleGetter, 'min'), # KX_CameraActuator
- 'getName': (replaceSimpleGetter, 'name'), # KX_Scene
- 'getNumAxes': (replaceSimpleGetter, 'numAxis'), # SCA_JoystickSensor
- 'getNumButtons': (replaceSimpleGetter, 'numButtons'), # SCA_JoystickSensor
- 'getNumHats': (replaceSimpleGetter, 'numHats'), # SCA_JoystickSensor
- 'getObjectList': (replaceSimpleGetter, 'objects'), # KX_Scene
- 'getOperation': (replaceSimpleGetter, 'mode'), # KX_SCA_DynamicActuator
- 'getOrientation': (replaceSimpleGetter, 'worldOrientation'), # KX_GameObject
- 'getOwner': (replaceSimpleGetter, 'owner'), # SCA_ILogicBrick
- 'getPara1': (replaceSimpleGetter, 'para1'), # SCA_RandomActuator
- 'getPara2': (replaceSimpleGetter, 'para2'), # SCA_RandomActuator
- 'getParent': (replaceSimpleGetter, 'parent'), # KX_GameObject
- 'getPID': (replaceSimpleGetter, 'pid'), # KX_ObjectActuator
- 'getPitch': (replaceSimpleGetter, 'pitch'), # KX_SoundActuator
- 'getPosition': (replaceSimpleGetter, 'worldPosition'), # KX_GameObject
- 'getPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor
- 'getPriority': (replaceSimpleGetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator
- 'getProjectionMatrix': (replaceSimpleGetter, 'projection_matrix'), # KX_Camera
- 'getProperty': (replaceSimpleGetter, 'propName'), # SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator
- 'getRayDirection': (replaceSimpleGetter, 'rayDirection'), # KX_MouseFocusSensor, KX_RaySensor
- 'getRaySource': (replaceSimpleGetter, 'raySource'), # KX_MouseFocusSensor
- 'getRayTarget': (replaceSimpleGetter, 'rayTarget'), # KX_MouseFocusSensor
- 'getRepeat': (replaceSimpleGetter, 'repeat'), # SCA_DelaySensor
- 'getRollOffFactor': (replaceSimpleGetter, 'rollOffFactor'), # KX_SoundActuator
- 'getScene': (replaceSimpleGetter, 'scene'), # KX_SceneActuator
- 'getScript': (replaceSimpleGetter, 'script'), # SCA_PythonController
- 'getSeed': (replaceSimpleGetter, 'seed'), # SCA_RandomActuator
- 'getStart': (replaceSimpleGetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
- 'getState': (replaceSimpleGetter, 'state'), # SCA_IController, KX_GameObject
- 'getSubject': (replaceSimpleGetter, 'subject'), # KX_NetworkMessageSensor
- 'getSubjects': (replaceSimpleGetter, 'subjects'), # KX_NetworkMessageSensor
- 'getThreshold': (replaceSimpleGetter, 'threshold'), # SCA_JoystickSensor
- 'getTime': (replaceSimpleGetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator
- 'getTouchMaterial': (replaceSimpleGetter, 'useMaterial'), # KX_TouchSensor
- 'getType': (replaceSimpleGetter, 'mode'), # SCA_PropertySensor
- 'getUse3D': (replaceSimpleGetter, 'use3D'), # KX_TrackToActuator
- 'getUseNegPulseMode': (replaceSimpleGetter, 'useNegPulseMode'), # SCA_ISensor
- 'getUsePosPulseMode': (replaceSimpleGetter, 'usePosPulseMode'), # SCA_ISensor
- 'getUseRestart': (replaceSimpleGetter, 'useRestart'), # KX_SceneActuator
- 'getValue': (replaceSimpleGetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator
- 'getVisible': (replaceSimpleGetter, 'visible'), # KX_GameObject
- 'getXY': (replaceSimpleGetter, 'useXY'), # KX_CameraActuator
- 'isConnected': (replaceSimpleGetter, 'connected'), # SCA_JoystickSensor
- 'isPositive': (replaceSimpleGetter, 'positive'), # SCA_ISensor
- 'isTriggered': (replaceSimpleGetter, 'triggered'), # SCA_ISensor
- 'setActuator': (replaceSimpleSetter, 'actuator'), # SCA_ActuatorSensor
- 'setBlendin': (replaceSimpleSetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator
- 'setBlendtime': (replaceSimpleSetter, 'blendTime'), # BL_ShapeActionActuator, BL_ActionActuator
- 'setBodyType': (replaceSimpleSetter, 'usePropBody'), # KX_NetworkMessageActuator
- 'setBody': (replaceSimpleSetter, 'body'), # KX_NetworkMessageActuator
- 'setButton': (replaceSimpleSetter, 'button'), # SCA_JoystickSensor
- 'setCamera': (replaceSimpleSetter, 'camera'), # KX_SceneActuator
- 'setContinue': (replaceSimpleSetter, 'useContinue'), # BL_ActionActuator
- 'setDamping': (replaceSimpleSetter, 'damping'), # KX_ObjectActuator
- 'setDelay': (replaceSimpleSetter, 'delay'), # SCA_DelaySensor
- 'setDuration': (replaceSimpleSetter, 'duration'), # SCA_DelaySensor
- 'setEnd': (replaceSimpleSetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
- 'setExecutePriority': (replaceSimpleSetter, 'executePriority'), # SCA_ILogicBrick
- 'setFile': (replaceSimpleSetter, 'fileName'), # KX_GameActuator
- 'setFilename': (replaceSimpleSetter, 'fileName'), # KX_SoundActuator
- 'setForceIpoActsLocal': (replaceSimpleSetter, 'useIpoLocal'), # KX_IpoActuator
- 'setFrame': (replaceSimpleSetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator
- 'setFrameProperty': (replaceSimpleSetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator
- 'setFrequency': (replaceSimpleSetter, 'frequency'), # SCA_ISensor
- 'setGain': (replaceSimpleSetter, 'volume'), # KX_SoundActuator, KX_CDActuator
- 'setHeight': (replaceSimpleSetter, 'height'), # KX_CameraActuator
- 'setHold1': (replaceSimpleSetter, 'hold1'), # SCA_KeyboardSensor
- 'setHold2': (replaceSimpleSetter, 'hold2'), # SCA_KeyboardSensor
- 'setInvert': (replaceSimpleSetter, 'invert'), # SCA_ISensor
- 'setIpoAdd': (replaceSimpleSetter, 'useIpoAdd'), # KX_IpoActuator
- 'setIpoAsForce': (replaceSimpleSetter, 'useIpoAsForce'), # KX_IpoActuator
- 'setKey': (replaceSimpleSetter, 'key'), # SCA_KeyboardSensor
- 'setLevel': (replaceSimpleSetter, 'level'), # SCA_ISensor
- 'setLooping': (replaceSimpleSetter, 'looping'), # KX_SoundActuator
- 'setMask': (replaceSimpleSetter, 'mask'), # KX_StateActuator
- 'setMax': (replaceSimpleSetter, 'max'), # KX_CameraActuator
- 'setMesh': (replaceSimpleSetter, 'mesh'), # KX_SCA_ReplaceMeshActuator
- 'setMin': (replaceSimpleSetter, 'min'), # KX_CameraActuator
- 'setPitch': (replaceSimpleSetter, 'pitch'), # KX_SoundActuator
- 'setPriority': (replaceSimpleSetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator
- 'setProjectionMatrix': (replaceSimpleSetter, 'projection_matrix'), # KX_Camera
- 'setProperty': (replaceSimpleSetter, 'propName'), # KX_IpoActuator, SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator
- 'setRepeat': (replaceSimpleSetter, 'repeat'), # SCA_DelaySensor
- 'setRollOffFactor': (replaceSimpleSetter, 'rollOffFactor'), # KX_SoundActuator
- 'setScene': (replaceSimpleSetter, 'scene'), # KX_SceneActuator
- 'setScript': (replaceSimpleSetter, 'script'), # SCA_PythonController
- 'setSeed': (replaceSimpleSetter, 'seed'), # SCA_RandomActuator
- 'setStart': (replaceSimpleSetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
- 'setState': (replaceSimpleSetter, 'state'), # KX_GameObject
- 'setSubject': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageActuator
- 'setSubjectFilterText': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageSensor
- 'setThreshold': (replaceSimpleSetter, 'threshold'), # SCA_JoystickSensor
- 'setTime': (replaceSimpleSetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator
- 'setToPropName': (replaceSimpleSetter, 'propName'), # KX_NetworkMessageActuator
- 'setType': (replaceSimpleSetter, 'mode'), # SCA_PropertySensor
- 'setUse3D': (replaceSimpleSetter, 'use3D'), # KX_TrackToActuator
- 'setUseNegPulseMode': (replaceSimpleSetter, 'useNegPulseMode'), # SCA_ISensor
- 'setUsePosPulseMode': (replaceSimpleSetter, 'usePosPulseMode'), # SCA_ISensor
- 'setUseRestart': (replaceSimpleSetter, 'useRestart'), # KX_SceneActuator
- 'setValue': (replaceSimpleSetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator
- 'setXY': (replaceSimpleSetter, 'useXY'), # KX_CameraActuator
-
- # Unimplemented!
- 'getLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
- 'setLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
- 'getAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
- 'setAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
- 'setAction': (notImplemented, ['BL_ShapeActionActuator', 'BL_ActionActuator']),
- 'set': (notImplemented, ['KX_VisibilityActuator', 'KX_IpoActuator']),
- 'getIndex': (notImplemented, ['SCA_JoystickSensor']),
- 'getMesh': (notImplemented, ['KX_SCA_ReplaceMeshActuator']),
- 'getObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']),
- 'setIndex': (notImplemented, ['SCA_JoystickSensor']),
- 'setObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']),
- 'setOperation': (notImplemented, ['KX_SCA_DynamicActuator', 'KX_StateActuator']),
- 'position': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']),
- 'orientation': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']),
- 'getDRot': (notImplemented, ['KX_ObjectActuator']),
- 'setDRot': (notImplemented, ['KX_ObjectActuator']),
- 'getDLoc': (notImplemented, ['KX_ObjectActuator']),
- 'setDLoc': (notImplemented, ['KX_ObjectActuator']),
- 'getTorque': (notImplemented, ['KX_ObjectActuator']),
- 'getTorque': (notImplemented, ['KX_ObjectActuator']),
- 'getForce': (notImplemented, ['KX_ObjectActuator']),
- 'setForce': (notImplemented, ['KX_ObjectActuator']),
-}
-
-def convert248to249(lines, log = True, logErrors = True, fileName = None):
- # Regular expression for finding attributes. For the string 'a.b', this
- # returns three groups: ['a.b', 'a.', 'b']. The last is the attribute name.
- attrRegex = re.compile(r'\.\s*' # Dot
- r'([a-zA-Z_]\w*)') # Identifier
-
- fileIdStr = ""
- if fileName:
- fileIdStr = fileName + ": "
- row = 0
- col = 0
- nconverted = 0
- nerrors = 0
- while row < len(lines):
- originalLine = lines[row]
- changed = False
- while col < len(lines[row]):
- # Don't search past comment. We have to check each iteration
- # because the line contents may have changed.
- commentStart = lines[row].find('#', col)
- if commentStart < 0:
- commentStart = len(lines[row])
-
- # Search for an attribute identifier.
- match = attrRegex.search(lines[row], col, commentStart)
- if not match:
- break
-
- attrName = match.group(1)
- if attributeRenameDict.has_key(attrName):
- # name is deprecated.
- func, closure = attributeRenameDict[attrName]
- try:
- # Convert!
- func(lines, row, match.start(1), match.end(1), closure)
- except ConversionError, e:
- # Insert a comment saying the conversion failed.
- print "ERROR: %sline %d, %s: %s\n" % (
- fileIdStr, row + 1, attrName, e)
- if logErrors:
- lines.insert(row,
- "##248## ERROR: %s: %s\n" %
- (attrName, e))
- row = row + 1
- nerrors = nerrors + 1
- else:
- changed = True
- nconverted = nconverted + 1
- # Search the rest of this line.
- col = match.start(1)
-
- if changed and log:
- # Insert a comment to showing difference in lines.
- if originalLine[-1] != '\n':
- originalLine = originalLine + '\n'
- lines.insert(row, "##248##%s" % originalLine)
- row = row + 1
-
- row = row + 1
- col = 0
- return nconverted, nerrors
-
-def usage():
- print "Usage: blender248to249.py [options] <infile> [outfile]"
- print "Options:"
- print "\t--nolog Don't include old lines as comments."
- print "\t--quieterrors Don't insert errors as comments."
-
-def runAsConsoleScript():
- '''Called when being run as a console script.'''
- try:
- opts, args = getopt.getopt(sys.argv[1:], "", ["nolog", "quieterrors"])
- except getopt.GetoptError, err:
- # print help information and exit:
- print str(err)
- usage()
- sys.exit(2)
-
- log = True
- logErrors = True
- for o, a in opts:
- if o == "--nolog":
- log = False
- elif o == "--quieterrors":
- logErrors = False
-
- try:
- inpath = args.pop(0)
- except IndexError:
- usage()
- sys.exit(2)
- try:
- outpath = args.pop(0)
- except IndexError:
- outpath = inpath
-
- infile = io.FileIO(inpath, 'r')
- # arbitrary file size of around 100kB
- lines = infile.readlines(100000)
- infile.close()
-
- nconverted, nerrors = convert248to249(lines, log, logErrors)
-
- outfile = io.FileIO(outpath, 'w')
- outfile.writelines(lines)
- outfile.close()
- print "Conversion finished. Modified %d attributes." % nconverted
- print "There were %d errors." % nerrors
- print "Please review all the changes."
-
-def runAsTextPlugin():
- '''Called when run as a text plugin.'''
-
- import Blender
- from Blender import Window, sys, Draw
- import BPyTextPlugin, bpy
-
- message = ("Convert Game Engine script from 4.48 API to 2.49 API%t|"
- "Run on active script only%x1|"
- "Run on ALL text buffers%x2")
- convertAllBuffers = Draw.PupMenu(message) == 2
-
- Window.WaitCursor(1)
- try:
- nconverted = 0
- nerrors = 0
-
- if convertAllBuffers:
- texts = bpy.data.texts
- else:
- if not bpy.data.texts.active:
- Draw.PupMenu("No active buffer.")
- return
- texts = [bpy.data.texts.active]
-
- Blender.SaveUndoState('Convert BGE 2.49')
-
- for txt in texts:
- bufName = txt.name
- if txt.lib:
- bufName = txt.lib + '/' + bufName
- lines = txt.asLines()
- for i in range(0, len(lines)):
- if not lines[i].endswith('\n'):
- lines[i] = lines[i] + '\n'
-
- nc, ne = convert248to249(lines, fileName = bufName)
- nconverted = nconverted + nc
- nerrors = nerrors + ne
- txt.clear()
- for line in lines:
- txt.write(line)
-
- finally:
- Window.WaitCursor(0)
-
- message = "Converted %d attributes." % nconverted
- if nerrors == 1:
- message = message + " There was 1 error (see console)."
- if nerrors > 1:
- message = message + " There were %d errors (see console)." % nerrors
- message = message + "|Please review all the changes."
- Draw.PupMenu(message)
-
-def main():
- try:
- import Blender
- except ImportError:
- runAsConsoleScript()
- else:
- runAsTextPlugin()
-
-# This lets you import the script without running it
-if __name__ == "__main__":
- import sys
- import getopt
- import io
- main()
diff --git a/release/scripts/wizard_bolt_factory.py b/release/scripts/wizard_bolt_factory.py
deleted file mode 100644
index 2d653b211d5..00000000000
--- a/release/scripts/wizard_bolt_factory.py
+++ /dev/null
@@ -1,2811 +0,0 @@
-#!BPY
-# -*- coding: latin-1 -*-
-"""
-Name: 'Bolt Factory'
-Blender: 248
-Group: 'Wizards'
-Tooltip: 'Create models of various types of screw fasteners.'
-"""
-
-__author__ = " Aaron Keith (Spudmn) "
-__version__ = "2.02 2009/06/10"
-__url__ = ["Author's site,http://sourceforge.net/projects/boltfactory/", "Blender,http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Misc/Bolt_Factory"]
-__bpydoc__ = """\
-Bolt_Factory.py
-
-Bolt Factory is a Python script for Blender 3D.
-
-The script allows the user to create models of various types of screw fasteners.
-
-For best results set the material to smooth and apply a Edge Split modifier
-with default settings.
-
-
-History:
- V2.02 10/06/09 by Aaron Keith
-
- -Added changes made by the Blender team.
-
- V2.01 26/05/09 by Aaron Keith
-
- - Fixed normal's on Lock Nut
-
-V2.00 22/05/09 by Aaron Keith
-
-- Better error checking.
-- Lock Nut and Hex Nut meshes added.
-- Pre-sets for common metric bolts and nuts.
-- Improved GUI.
-- Meshes scaled to a smaller size
-- Fixed bug when using crest and root percent other than 10%
-- Can now create meshes in Edit Mode. This will add to the
- current mesh and align with the current view.
-
-V1.00 01/04/08 by Aaron Keith
-
-- This version is very much a work in progress.
-- This is my first attempt to program in Python. This version is
- unpolished and doesn't do much error checking. Therefore
- if the user sets strange variable the model created will be
- as equally strange.
-
-- To Do:
-- Better error checking.
-- More Head and Bit types.
-- Better documentation.
-
-
-"""
-
-# --------------------------------------------------------------------------
-# Bolt_Factory.py
-# --------------------------------------------------------------------------
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# Copyright (C) 2009: Aaron Keith
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-# --------------------------------------------------------------------------
-
-
-
-
-import Blender
-from Blender import Draw, BGL,Mesh
-from Blender import *
-from math import *
-from Blender import Mathutils
-from Blender.Mathutils import *
-
-
-#Global_Scale = 0.001 #1 blender unit = X mm
-Global_Scale = 0.1 #1 blender unit = X mm
-#Global_Scale = 1.0 #1 blender unit = X mm
-Global_NutRad = 0.0
-MAX_INPUT_NUMBER = 50
-
-No_Event,On_Preset_Click,On_Apply_Click,On_Create_Click,On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click,On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click,On_Exit_Click,On_Model_Bolt_Click,On_Model_Nut_Click,On_Hex_Nut_Click,On_Lock_Nut_Click,On_Test_Click = range(17) # this is like a ENUM
-
-
-Head_Type={'HEX' : [Draw.Create(1),On_Hex_Click,""],
- 'CAP' : [Draw.Create(0),On_Cap_Click,""],
- 'DOME': [Draw.Create(0),On_Dome_Click,""],
- 'PAN' : [Draw.Create(0),On_Pan_Click,""]}
-
-
-Bit_Type={'NONE' : [Draw.Create(1),On_Bit_None_Click,""],
- 'ALLEN' : [Draw.Create(0),On_Bit_Allen_Click,""],
- 'PHILLIPS': [Draw.Create(0),On_Bit_Philips_Click,""]}
-
-Model_Type={'BOLT' : [Draw.Create(1),On_Model_Bolt_Click,"Bolt Settings"],
- 'NUT' : [Draw.Create(0),On_Model_Nut_Click,"Nut Settings"]}
-
-Nut_Type={'HEX' : [Draw.Create(1),On_Hex_Nut_Click,""],
- 'LOCK' : [Draw.Create(0),On_Lock_Nut_Click,""]}
-
-
-Phillips_Bit_Depth = Draw.Create(3.27)
-Philips_Bit_Dia = Draw.Create(5.20)
-
-Allen_Bit_Depth = Draw.Create(4.0)
-Allen_Bit_Flat_Distance = Draw.Create(6.0)
-
-Hex_Head_Height = Draw.Create(5.3)
-Hex_Head_Flat_Distance = Draw.Create(13.0)
-
-Cap_Head_Dia = Draw.Create(13.5)
-Cap_Head_Height = Draw.Create(8.0)
-
-Dome_Head_Dia = Draw.Create(16.0)
-
-Pan_Head_Dia = Draw.Create(16.0)
-
-Shank_Dia = Draw.Create(8.0)
-Shank_Length = Draw.Create(0.0)
-
-Thread_Length = Draw.Create(16.0)
-Major_Dia = Draw.Create(8.0)
-Minor_Dia = Draw.Create(6.917)
-Pitch = Draw.Create(1.0)
-Crest_Percent = Draw.Create(10)
-Root_Percent = Draw.Create(10)
-
-Hex_Nut_Height = Draw.Create(8.0)
-Hex_Nut_Flat_Distance = Draw.Create(13.0)
-
-Preset_Menu = Draw.Create(5)
-
-
-##########################################################################################
-##########################################################################################
-## Miscellaneous Utilities
-##########################################################################################
-##########################################################################################
-
-# Returns a list of verts rotated by the given matrix. Used by SpinDup
-def Rot_Mesh(verts,matrix):
- return [list(Vector(v) * matrix) for v in verts]
-
-# Returns a list of faces that has there index incremented by offset
-def Copy_Faces(faces,offset):
- ret = []
- for f in faces:
- fsub = []
- for i in range(len(f)):
- fsub.append(f[i]+ offset)
- ret.append(fsub)
- return ret
-
-
-# Much like Blenders built in SpinDup.
-def SpinDup(VERTS,FACES,DEGREE,DIVISIONS,AXIS):
- verts=[]
- faces=[]
-
- if DIVISIONS == 0:
- DIVISIONS = 1
-
- step = DEGREE/DIVISIONS # set step so pieces * step = degrees in arc
-
- for i in xrange(int(DIVISIONS)):
- rotmat = Mathutils.RotationMatrix(step*i, 4, AXIS) # 4x4 rotation matrix, 30d about the x axis.
- Rot = Rot_Mesh(VERTS,rotmat)
- faces.extend(Copy_Faces(FACES,len(verts)))
- verts.extend(Rot)
- return verts,faces
-
-
-# Returns a list of verts that have been moved up the z axis by DISTANCE
-def Move_Verts_Up_Z(VERTS,DISTANCE):
- return [[v[0],v[1],v[2]+DISTANCE] for v in VERTS]
-
-
-# Returns a list of verts and faces that has been mirrored in the AXIS
-def Mirror_Verts_Faces(VERTS,FACES,AXIS,FLIP_POINT =0):
- ret_vert = []
- ret_face = []
- offset = len(VERTS)
- if AXIS == 'y':
- for v in VERTS:
- Delta = v[0] - FLIP_POINT
- ret_vert.append([FLIP_POINT-Delta,v[1],v[2]])
- if AXIS == 'x':
- for v in VERTS:
- Delta = v[1] - FLIP_POINT
- ret_vert.append([v[0],FLIP_POINT-Delta,v[2]])
- if AXIS == 'z':
- for v in VERTS:
- Delta = v[2] - FLIP_POINT
- ret_vert.append([v[0],v[1],FLIP_POINT-Delta])
-
- for f in FACES:
- fsub = []
- for i in range(len(f)):
- fsub.append(f[i]+ offset)
- fsub.reverse() # flip the order to make norm point out
- ret_face.append(fsub)
-
- return ret_vert,ret_face
-
-
-
-# Returns a list of faces that
-# make up an array of 4 point polygon.
-def Build_Face_List_Quads(OFFSET,COLUM,ROW,FLIP = 0):
- Ret =[]
- RowStart = 0;
- for j in range(ROW):
- for i in range(COLUM):
- Res1 = RowStart + i;
- Res2 = RowStart + i + (COLUM +1)
- Res3 = RowStart + i + (COLUM +1) +1
- Res4 = RowStart+i+1
- if FLIP:
- Ret.append([OFFSET+Res1,OFFSET+Res2,OFFSET+Res3,OFFSET+Res4])
- else:
- Ret.append([OFFSET+Res4,OFFSET+Res3,OFFSET+Res2,OFFSET+Res1])
- RowStart += COLUM+1
- return Ret
-
-
-# Returns a list of faces that makes up a fill pattern for a
-# circle
-def Fill_Ring_Face(OFFSET,NUM,FACE_DOWN = 0):
- Ret =[]
- Face = [1,2,0]
- TempFace = [0,0,0]
- A = 0
- B = 1
- C = 2
- if NUM < 3:
- return None
- for i in range(NUM-2):
- if (i%2):
- TempFace[0] = Face[C];
- TempFace[1] = Face[C] + 1;
- TempFace[2] = Face[B];
- if FACE_DOWN:
- Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
- else:
- Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
- else:
- TempFace[0] =Face[C];
- if Face[C] == 0:
- TempFace[1] = NUM-1;
- else:
- TempFace[1] = Face[C] - 1;
- TempFace[2] = Face[B];
- if FACE_DOWN:
- Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
- else:
- Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
-
- Face[0] = TempFace[0]
- Face[1] = TempFace[1]
- Face[2] = TempFace[2]
- return Ret
-
-
-##########################################################################################
-##########################################################################################
-## Converter Functions For Bolt Factory
-##########################################################################################
-##########################################################################################
-
-
-def Flat_To_Radius(FLAT):
- h = (float(FLAT)/2)/cos(radians(30))
- return h
-
-def Get_Phillips_Bit_Height(Bit_Dia):
- Flat_Width_half = (Bit_Dia*(0.5/1.82))/2.0
- Bit_Rad = Bit_Dia / 2.0
- x = Bit_Rad - Flat_Width_half
- y = tan(radians(60))*x
- return y
-
-##########################################################################################
-##########################################################################################
-## Error Checking
-##########################################################################################
-##########################################################################################
-
-
-def Error_Check():
-
- #global Phillips_Bit_Depth
- #global Philips_Bit_Dia
-
- #global Allen_Bit_Depth
- #global Allen_Bit_Flat_Distance
-
- #global Hex_Head_Height
- #global Hex_Head_Flat_Distance
-
- #global Cap_Head_Dia
- #global Cap_Head_Height
-
-
- #global Dome_Head_Dia
-
- #global Pan_Head_Dia
-
- #global Shank_Dia
- #global Shank_Length
-
- global Thread_Length
- global Major_Dia
- global Minor_Dia
- global Pitch
- global Hex_Nut_Flat_Distance
- global Model_Type
- #global Crest_Percent
- #global Root_Percent
-
- Error_Result = 0
-
- if Minor_Dia.val >= Major_Dia.val:
- error_txt = "Error%t|Major Dia must be larger than Minor Dia"
- Blender.Draw.PupMenu(error_txt)
- print error_txt
- Error_Result = TRUE
-
- elif (Model_Type['BOLT'][0].val) and ((Pitch.val*7.0) > Thread_Length.val):
- error_txt = "Error%t|Thread length must be at least 7 times the Pitch"
- Blender.Draw.PupMenu(error_txt)
- print error_txt
- Error_Result = TRUE
-
- elif (Model_Type['NUT'][0].val) and (Hex_Nut_Flat_Distance.val < Major_Dia.val):
- error_txt = "Error%t|Nut Flat Distance must be greater than Major Dia"
- Blender.Draw.PupMenu(error_txt)
- print error_txt
- Error_Result = TRUE
-
- elif (Model_Type['NUT'][0].val) and ((Pitch.val * 2.5 )> Hex_Nut_Height.val):
- error_txt = "Error%t|Nut Height must be greater than 2.5 * Pitch"
- Blender.Draw.PupMenu(error_txt)
- print error_txt
- Error_Result = TRUE
-
- elif (Model_Type['BOLT'][0].val):
- Check_Head_Height = None
- Check_Bit_Height = None
- if (Bit_Type['ALLEN'][0].val):
- Check_Bit_Height = Allen_Bit_Depth.val
- if (Bit_Type['PHILLIPS'][0].val):
- Check_Bit_Height = Phillips_Bit_Depth.val
- if (Head_Type['HEX'][0].val):
- Check_Head_Height = Hex_Head_Height.val
- if (Head_Type['CAP'][0].val):
- Check_Head_Height = Cap_Head_Height.val
-
- if Check_Head_Height != None and Check_Bit_Height != None :
- if Check_Bit_Height > Check_Head_Height:
- error_txt = "Error%t|Bit Depth must not be greater that Head Height"
- Blender.Draw.PupMenu(error_txt)
- print error_txt
- Error_Result = TRUE
-
-
- return Error_Result
-
-
-
-##########################################################################################
-##########################################################################################
-## Create Allen Bit
-##########################################################################################
-##########################################################################################
-
-
-def Allen_Fill(OFFSET,FLIP= 0):
- faces = []
- Lookup = [[19,1,0],
- [19,2,1],
- [19,3,2],
- [19,20,3],
- [20,4,3],
- [20,5,4],
- [20,6,5],
- [20,7,6],
- [20,8,7],
- [20,9,8],
-
- [20,21,9],
-
- [21,10,9],
- [21,11,10],
- [21,12,11],
- [21,13,12],
- [21,14,13],
- [21,15,14],
-
- [21,22,15],
- [22,16,15],
- [22,17,16],
- [22,18,17]
- ]
- for i in Lookup:
- if FLIP:
- faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
- else:
- faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
-
- return faces
-
-def Allen_Bit_Dia(FLAT_DISTANCE):
- Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30))
- return (Flat_Radius * 1.05) * 2.0
-
-def Allen_Bit_Dia_To_Flat(DIA):
- Flat_Radius = (DIA/2.0)/1.05
- return (Flat_Radius * cos (radians(30)))* 2.0
-
-
-
-def Create_Allen_Bit(FLAT_DISTANCE,HEIGHT):
- Div = 36
- verts = []
- faces = []
-
- Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30))
- OUTTER_RADIUS = Flat_Radius * 1.05
- Outter_Radius_Height = Flat_Radius * (0.1/5.77)
- FaceStart_Outside = len(verts)
- Deg_Step = 360.0 /float(Div)
-
- for i in range((Div/2)+1): # only do half and mirror later
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,0])
-
- FaceStart_Inside = len(verts)
-
- Deg_Step = 360.0 /float(6)
- for i in range((6/2)+1):
- x = sin(radians(i*Deg_Step))* Flat_Radius
- y = cos(radians(i*Deg_Step))* Flat_Radius
- verts.append([x,y,0-Outter_Radius_Height])
-
- faces.extend(Allen_Fill(FaceStart_Outside,0))
-
-
- FaceStart_Bottom = len(verts)
-
- Deg_Step = 360.0 /float(6)
- for i in range((6/2)+1):
- x = sin(radians(i*Deg_Step))* Flat_Radius
- y = cos(radians(i*Deg_Step))* Flat_Radius
- verts.append([x,y,0-HEIGHT])
-
- faces.extend(Build_Face_List_Quads(FaceStart_Inside,3,1,TRUE))
- faces.extend(Fill_Ring_Face(FaceStart_Bottom,4))
-
-
- M_Verts,M_Faces = Mirror_Verts_Faces(verts,faces,'y')
- verts.extend(M_Verts)
- faces.extend(M_Faces)
-
- return verts,faces,OUTTER_RADIUS * 2.0
-
-
-##########################################################################################
-##########################################################################################
-## Create Phillips Bit
-##########################################################################################
-##########################################################################################
-
-
-def Phillips_Fill(OFFSET,FLIP= 0):
- faces = []
- Lookup = [[0,1,10],
- [1,11,10],
- [1,2,11],
- [2,12,11],
-
- [2,3,12],
- [3,4,12],
- [4,5,12],
- [5,6,12],
- [6,7,12],
-
- [7,13,12],
- [7,8,13],
- [8,14,13],
- [8,9,14],
-
-
- [10,11,16,15],
- [11,12,16],
- [12,13,16],
- [13,14,17,16],
- [15,16,17,18]
-
-
- ]
- for i in Lookup:
- if FLIP:
- if len(i) == 3:
- faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
- else:
- faces.append([OFFSET+i[3],OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
- else:
- if len(i) == 3:
- faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
- else:
- faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2],OFFSET+i[3]])
- return faces
-
-
-
-def Create_Phillips_Bit(FLAT_DIA,FLAT_WIDTH,HEIGHT):
- Div = 36
- verts = []
- faces = []
-
- FLAT_RADIUS = FLAT_DIA * 0.5
- OUTTER_RADIUS = FLAT_RADIUS * 1.05
-
- Flat_Half = float(FLAT_WIDTH)/2.0
-
- FaceStart_Outside = len(verts)
- Deg_Step = 360.0 /float(Div)
- for i in range((Div/4)+1): # only do half and mirror later
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,0])
-
-
- FaceStart_Inside = len(verts)
- verts.append([0,FLAT_RADIUS,0]) #10
- verts.append([Flat_Half,FLAT_RADIUS,0]) #11
- verts.append([Flat_Half,Flat_Half,0]) #12
- verts.append([FLAT_RADIUS,Flat_Half,0]) #13
- verts.append([FLAT_RADIUS,0,0]) #14
-
-
- verts.append([0,Flat_Half,0-HEIGHT]) #15
- verts.append([Flat_Half,Flat_Half,0-HEIGHT]) #16
- verts.append([Flat_Half,0,0-HEIGHT]) #17
-
- verts.append([0,0,0-HEIGHT]) #18
-
- faces.extend(Phillips_Fill(FaceStart_Outside,TRUE))
-
- Spin_Verts,Spin_Face = SpinDup(verts,faces,360,4,'z')
-
- return Spin_Verts,Spin_Face,OUTTER_RADIUS * 2
-
-
-##########################################################################################
-##########################################################################################
-## Create Head Types
-##########################################################################################
-##########################################################################################
-
-def Max_Pan_Bit_Dia(HEAD_DIA):
- HEAD_RADIUS = HEAD_DIA * 0.5
- XRad = HEAD_RADIUS * 1.976
- return (sin(radians(10))*XRad) * 2.0
-
-
-def Create_Pan_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
-
- DIV = 36
- HOLE_RADIUS = HOLE_DIA * 0.5
- HEAD_RADIUS = HEAD_DIA * 0.5
- SHANK_RADIUS = SHANK_DIA * 0.5
-
- verts = []
- faces = []
- Row = 0
- BEVEL = HEIGHT * 0.01
- #Dome_Rad = HEAD_RADIUS * (1.0/1.75)
-
- Dome_Rad = HEAD_RADIUS * 1.12
- RAD_Offset = HEAD_RADIUS * 0.96
- OtherRad = HEAD_RADIUS * 0.16
- OtherRad_X_Offset = HEAD_RADIUS * 0.84
- OtherRad_Z_Offset = HEAD_RADIUS * 0.504
- XRad = HEAD_RADIUS * 1.976
- ZRad = HEAD_RADIUS * 1.768
- EndRad = HEAD_RADIUS * 0.284
- EndZOffset = HEAD_RADIUS * 0.432
- HEIGHT = HEAD_RADIUS * 0.59
-
-# Dome_Rad = 5.6
-# RAD_Offset = 4.9
-# OtherRad = 0.8
-# OtherRad_X_Offset = 4.2
-# OtherRad_Z_Offset = 2.52
-# XRad = 9.88
-# ZRad = 8.84
-# EndRad = 1.42
-# EndZOffset = 2.16
-# HEIGHT = 2.95
-
- FaceStart = FACE_OFFSET
-
- z = cos(radians(10))*ZRad
- verts.append([HOLE_RADIUS,0.0,(0.0-ZRad)+z])
- Start_Height = 0 - ((0.0-ZRad)+z)
- Row += 1
-
- #for i in range(0,30,10): was 0 to 30 more work needed to make this look good.
- for i in range(10,30,10):
- x = sin(radians(i))*XRad
- z = cos(radians(i))*ZRad
- verts.append([x,0.0,(0.0-ZRad)+z])
- Row += 1
-
- for i in range(20,140,10):
- x = sin(radians(i))*EndRad
- z = cos(radians(i))*EndRad
- if ((0.0 - EndZOffset)+z) < (0.0-HEIGHT):
- verts.append([(HEAD_RADIUS -EndRad)+x,0.0,0.0 - HEIGHT])
- else:
- verts.append([(HEAD_RADIUS -EndRad)+x,0.0,(0.0 - EndZOffset)+z])
- Row += 1
-
-
- verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)])
- Row += 1
-
- verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)-Start_Height])
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
-
- Global_Head_Height = HEIGHT ;
-
-
- return Move_Verts_Up_Z(sVerts,Start_Height),faces,HEIGHT
-
-
-
-def Create_Dome_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
- DIV = 36
- HOLE_RADIUS = HOLE_DIA * 0.5
- HEAD_RADIUS = HEAD_DIA * 0.5
- SHANK_RADIUS = SHANK_DIA * 0.5
-
- verts = []
- faces = []
- Row = 0
- BEVEL = HEIGHT * 0.01
- #Dome_Rad = HEAD_RADIUS * (1.0/1.75)
-
- Dome_Rad = HEAD_RADIUS * 1.12
- #Head_Height = HEAD_RADIUS * 0.78
- RAD_Offset = HEAD_RADIUS * 0.98
- Dome_Height = HEAD_RADIUS * 0.64
- OtherRad = HEAD_RADIUS * 0.16
- OtherRad_X_Offset = HEAD_RADIUS * 0.84
- OtherRad_Z_Offset = HEAD_RADIUS * 0.504
-
-
-# Dome_Rad = 5.6
-# RAD_Offset = 4.9
-# Dome_Height = 3.2
-# OtherRad = 0.8
-# OtherRad_X_Offset = 4.2
-# OtherRad_Z_Offset = 2.52
-#
-
- FaceStart = FACE_OFFSET
-
- verts.append([HOLE_RADIUS,0.0,0.0])
- Row += 1
-
-
- for i in range(0,60,10):
- x = sin(radians(i))*Dome_Rad
- z = cos(radians(i))*Dome_Rad
- if ((0.0-RAD_Offset)+z) <= 0:
- verts.append([x,0.0,(0.0-RAD_Offset)+z])
- Row += 1
-
-
- for i in range(60,160,10):
- x = sin(radians(i))*OtherRad
- z = cos(radians(i))*OtherRad
- z = (0.0-OtherRad_Z_Offset)+z
- if z < (0.0-Dome_Height):
- z = (0.0-Dome_Height)
- verts.append([OtherRad_X_Offset+x,0.0,z])
- Row += 1
-
- verts.append([SHANK_RADIUS,0.0,(0.0-Dome_Height)])
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
-
- return sVerts,faces,Dome_Height
-
-
-
-def Create_Cap_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2):
- DIV = 36
-
- HOLE_RADIUS = HOLE_DIA * 0.5
- HEAD_RADIUS = HEAD_DIA * 0.5
- SHANK_RADIUS = SHANK_DIA * 0.5
-
- verts = []
- faces = []
- Row = 0
- BEVEL = HEIGHT * 0.01
-
-
- FaceStart = len(verts)
-
- verts.append([HOLE_RADIUS,0.0,0.0])
- Row += 1
-
- #rad
-
- for i in range(0,100,10):
- x = sin(radians(i))*RAD1
- z = cos(radians(i))*RAD1
- verts.append([(HEAD_RADIUS-RAD1)+x,0.0,(0.0-RAD1)+z])
- Row += 1
-
-
- verts.append([HEAD_RADIUS,0.0,0.0-HEIGHT+BEVEL])
- Row += 1
-
- verts.append([HEAD_RADIUS-BEVEL,0.0,0.0-HEIGHT])
- Row += 1
-
- #rad2
-
- for i in range(0,100,10):
- x = sin(radians(i))*RAD2
- z = cos(radians(i))*RAD2
- verts.append([(SHANK_RADIUS+RAD2)-x,0.0,(0.0-HEIGHT-RAD2)+z])
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
-
- return sVerts,faces,HEIGHT+RAD2
-
-
-
-def Create_Hex_Head(FLAT,HOLE_DIA,SHANK_DIA,HEIGHT):
-
- verts = []
- faces = []
- HOLE_RADIUS = HOLE_DIA * 0.5
- Half_Flat = FLAT/2
- TopBevelRadius = Half_Flat - (Half_Flat* (0.05/8))
- Undercut_Height = (Half_Flat* (0.05/8))
- Shank_Bevel = (Half_Flat* (0.05/8))
- Flat_Height = HEIGHT - Undercut_Height - Shank_Bevel
- #Undercut_Height = 5
- SHANK_RADIUS = SHANK_DIA/2
- Row = 0;
-
- verts.append([0.0,0.0,0.0])
-
-
- FaceStart = len(verts)
- #inner hole
-
- x = sin(radians(0))*HOLE_RADIUS
- y = cos(radians(0))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/6))*HOLE_RADIUS
- y = cos(radians(60/6))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/3))*HOLE_RADIUS
- y = cos(radians(60/3))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/2))*HOLE_RADIUS
- y = cos(radians(60/2))*HOLE_RADIUS
- verts.append([x,y,0.0])
- Row += 1
-
- #bevel
-
- x = sin(radians(0))*TopBevelRadius
- y = cos(radians(0))*TopBevelRadius
- vec1 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/6))*TopBevelRadius
- y = cos(radians(60/6))*TopBevelRadius
- vec2 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/3))*TopBevelRadius
- y = cos(radians(60/3))*TopBevelRadius
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/2))*TopBevelRadius
- y = cos(radians(60/2))*TopBevelRadius
- vec4 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,0.0])
- Row += 1
-
- #Flats
-
- x = tan(radians(0))*Half_Flat
- dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0])
- verts.append([x,Half_Flat,-dvec.length])
-
-
- x = tan(radians(60/6))*Half_Flat
- dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0])
- verts.append([x,Half_Flat,-dvec.length])
-
-
- x = tan(radians(60/3))*Half_Flat
- dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0])
- Lowest_Point = -dvec.length
- verts.append([x,Half_Flat,-dvec.length])
-
-
- x = tan(radians(60/2))*Half_Flat
- dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0])
- Lowest_Point = -dvec.length
- verts.append([x,Half_Flat,-dvec.length])
- Row += 1
-
- #down Bits Tri
- x = tan(radians(0))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/6))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/3))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/2))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
- Row += 1
-
- #down Bits
-
- x = tan(radians(0))*Half_Flat
- verts.append([x,Half_Flat,-Flat_Height])
-
- x = tan(radians(60/6))*Half_Flat
- verts.append([x,Half_Flat,-Flat_Height])
-
- x = tan(radians(60/3))*Half_Flat
- verts.append([x,Half_Flat,-Flat_Height])
-
- x = tan(radians(60/2))*Half_Flat
- verts.append([x,Half_Flat,-Flat_Height])
- Row += 1
-
-
- #under cut
-
- x = sin(radians(0))*Half_Flat
- y = cos(radians(0))*Half_Flat
- vec1 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height])
-
- x = sin(radians(60/6))*Half_Flat
- y = cos(radians(60/6))*Half_Flat
- vec2 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height])
-
- x = sin(radians(60/3))*Half_Flat
- y = cos(radians(60/3))*Half_Flat
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height])
-
- x = sin(radians(60/2))*Half_Flat
- y = cos(radians(60/2))*Half_Flat
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height])
- Row += 1
-
- #under cut down bit
- x = sin(radians(0))*Half_Flat
- y = cos(radians(0))*Half_Flat
- vec1 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/6))*Half_Flat
- y = cos(radians(60/6))*Half_Flat
- vec2 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/3))*Half_Flat
- y = cos(radians(60/3))*Half_Flat
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/2))*Half_Flat
- y = cos(radians(60/2))*Half_Flat
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
- Row += 1
-
- #under cut to Shank BEVEAL
- x = sin(radians(0))*(SHANK_RADIUS+Shank_Bevel)
- y = cos(radians(0))*(SHANK_RADIUS+Shank_Bevel)
- vec1 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
- y = cos(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
- vec2 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
- y = cos(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
- y = cos(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
- Row += 1
-
- #under cut to Shank BEVEAL
- x = sin(radians(0))*SHANK_RADIUS
- y = cos(radians(0))*SHANK_RADIUS
- vec1 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
-
- x = sin(radians(60/6))*SHANK_RADIUS
- y = cos(radians(60/6))*SHANK_RADIUS
- vec2 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
-
- x = sin(radians(60/3))*SHANK_RADIUS
- y = cos(radians(60/3))*SHANK_RADIUS
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
-
- x = sin(radians(60/2))*SHANK_RADIUS
- y = cos(radians(60/2))*SHANK_RADIUS
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
- Row += 1
-
-
- #Global_Head_Height = 0 - (-HEIGHT-0.1)
- faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
-
-
- Mirror_Verts,Mirror_Faces = Mirror_Verts_Faces(verts,faces,'y')
- verts.extend(Mirror_Verts)
- faces.extend(Mirror_Faces)
-
- Spin_Verts,Spin_Faces = SpinDup(verts,faces,360,6,'z')
-
- return Spin_Verts,Spin_Faces,0 - (-HEIGHT)
-
-
-##########################################################################################
-##########################################################################################
-## Create Bolt
-##########################################################################################
-##########################################################################################
-
-
-
-def MakeBolt():
- global Phillips_Bit_Depth
- global Philips_Bit_Dia
-
- global Allen_Bit_Depth
- global Allen_Bit_Flat_Distance
-
- global Hex_Head_Height
- global Hex_Head_Flat_Distance
-
- global Cap_Head_Dia
- global Cap_Head_Height
-
-
- global Dome_Head_Dia
-
- global Pan_Head_Dia
-
- global Shank_Dia
- global Shank_Length
-
- global Thread_Length
- global Major_Dia
- global Minor_Dia
- global Pitch
- global Crest_Percent
- global Root_Percent
-
- verts = []
- faces = []
- Bit_Verts = []
- Bit_Faces = []
- Bit_Dia = 0.001
- Head_Verts = []
- Head_Faces= []
- Head_Height = 0.0
- ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Flat_Distance.val # set default
-
-
- Head_Height = Hex_Head_Height.val # will be changed by the Head Functions
-
- if Bit_Type['ALLEN'][0].val and Head_Type['PAN'][0].val:
- #need to size Allen bit if it is too big.
- if Allen_Bit_Dia(Allen_Bit_Flat_Distance.val) > Max_Pan_Bit_Dia(Pan_Head_Dia.val):
- ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Dia_To_Flat(Max_Pan_Bit_Dia(Pan_Head_Dia.val)) * 1.05
- print "Resized Allen Bit Flat Distance to ",ReSized_Allen_Bit_Flat_Distance
-
- #bit Mesh
- if Bit_Type['ALLEN'][0].val:
- Bit_Verts,Bit_Faces,Bit_Dia = Create_Allen_Bit(ReSized_Allen_Bit_Flat_Distance,Allen_Bit_Depth.val)
-
- if Bit_Type['PHILLIPS'][0].val:
- Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(Philips_Bit_Dia.val,Philips_Bit_Dia.val*(0.5/1.82),Phillips_Bit_Depth.val)
-
-
- #Head Mesh
- if Head_Type['HEX'][0].val:
- Head_Verts,Head_Faces,Head_Height = Create_Hex_Head(Hex_Head_Flat_Distance.val,Bit_Dia,Shank_Dia.val,Hex_Head_Height.val)
-
- elif Head_Type['CAP'][0].val:
- Head_Verts,Head_Faces,Head_Height = Create_Cap_Head(Bit_Dia,Cap_Head_Dia.val,Shank_Dia.val,Cap_Head_Height.val,Cap_Head_Dia.val*(1.0/19.0),Cap_Head_Dia.val*(1.0/19.0))
-
- elif Head_Type['DOME'][0].val:
- Head_Verts,Head_Faces,Head_Height = Create_Dome_Head(Bit_Dia,Dome_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
-
- elif Head_Type['PAN'][0].val:
- Head_Verts,Head_Faces,Head_Height = Create_Pan_Head(Bit_Dia,Pan_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
-
-
- Face_Start = len(verts)
- verts.extend(Move_Verts_Up_Z(Bit_Verts,Head_Height))
- faces.extend(Copy_Faces(Bit_Faces,Face_Start))
-
- Face_Start = len(verts)
- verts.extend(Move_Verts_Up_Z(Head_Verts,Head_Height))
- faces.extend(Copy_Faces(Head_Faces,Face_Start))
-
- Face_Start = len(verts)
- Thread_Verts,Thread_Faces,Thread_Height = Create_External_Thread(Shank_Dia.val,Shank_Length.val,Minor_Dia.val,Major_Dia.val,Pitch.val,Thread_Length.val,Crest_Percent.val,Root_Percent.val)
-
- verts.extend(Move_Verts_Up_Z(Thread_Verts,00))
- faces.extend(Copy_Faces(Thread_Faces,Face_Start))
-
- return Move_Verts_Up_Z(verts,Thread_Height),faces
-
-
-
-
-
-
-
-##########################################################################################
-##########################################################################################
-## Create Internal Thread
-##########################################################################################
-##########################################################################################
-
-
-def Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
-
-
- Ret_Row = 0;
-
- Height_Offset = Height_Offset + PITCH #Move the offset up so that the verts start at
- #at the correct place (Height_Start)
-
- Half_Pitch = float(PITCH)/2
- Height_Start = Height_Offset - PITCH
- Height_Step = float(PITCH)/float(DIV)
- Deg_Step = 360.0 /float(DIV)
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
-
- Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
- for j in range(1):
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z])
- Height_Offset -= Crest_Height
- Ret_Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z ])
- Height_Offset -= Crest_to_Root_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Height_Offset -= Root_Height
- Ret_Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
-
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Height_Offset -= Root_to_Crest_Height
- Ret_Row += 1
-
- return Ret_Row,Height_Offset
-
-
-def Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
-
-
- Ret_Row = 0;
-
- Half_Pitch = float(PITCH)/2
- #Height_End = Height_Offset - PITCH - PITCH - PITCH- PITCH - PITCH- PITCH
- Height_End = Height_Offset - PITCH
- #Height_End = -2.1
- Height_Step = float(PITCH)/float(DIV)
- Deg_Step = 360.0 /float(DIV)
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
-
-
- Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
-
- Num = 0
-
- for j in range(2):
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z < Height_End:
- z = Height_End
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z])
- Height_Offset -= Crest_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z < Height_End:
- z = Height_End
-
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z ])
- Height_Offset -= Crest_to_Root_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z < Height_End:
- z = Height_End
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- if j == Num:
- x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
- y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
- if j > Num:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS)
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
-
- verts.append([x,y,z ])
- Height_Offset -= Root_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z < Height_End:
- z = Height_End
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
-
- if j == Num:
- x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
- y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
- if j > Num:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS )
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
-
- verts.append([x,y,z ])
- Height_Offset -= Root_to_Crest_Height
- Ret_Row += 1
-
-
- return Ret_Row,Height_End # send back Height End as this is the lowest point
-
-
-def Create_Internal_Thread(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,INTERNAL = 1):
- verts = []
- faces = []
-
- DIV = 36
-
- INNER_RADIUS = INNER_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Half_Pitch = float(PITCH)/2
- Deg_Step = 360.0 /float(DIV)
- Height_Step = float(PITCH)/float(DIV)
-
- Num = int(round((HEIGHT- PITCH)/PITCH)) # less one pitch for the start and end that is 1/2 pitch high
-
- Col = 0
- Row = 0
-
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
- Height_Offset = 0
- FaceStart = len(verts)
-
- Row_Inc,Height_Offset = Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
- Row += Row_Inc
-
- for j in range(Num):
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,Height_Offset - (Height_Step*i) ])
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,Height_Offset - (Height_Step*i) ])
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- verts.append([x,y,Height_Offset - (Height_Step*i) ])
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- verts.append([x,y,Height_Offset - (Height_Step*i) ])
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
-
- Row_Inc,Height_Offset = Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
- Row += Row_Inc
-
- faces.extend(Build_Face_List_Quads(FaceStart,DIV,Row -1,INTERNAL))
-
- return verts,faces,0 - Height_Offset
-
-
-
-##########################################################################################
-##########################################################################################
-## Create External Thread
-##########################################################################################
-##########################################################################################
-
-
-
-def Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
-
-
- Ret_Row = 0;
-
- Half_Pitch = float(PITCH)/2
- Height_Start = Height_Offset - PITCH
- Height_Step = float(PITCH)/float(DIV)
- Deg_Step = 360.0 /float(DIV)
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
-#theard start
-
- Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
- for j in range(4):
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z])
- Height_Offset -= Crest_Height
- Ret_Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z ])
- Height_Offset -= Crest_to_Root_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Height_Offset -= Root_Height
- Ret_Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
-
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Height_Offset -= Root_to_Crest_Height
- Ret_Row += 1
-
- return Ret_Row,Height_Offset
-
-
-def Create_Shank_Verts(START_DIA,OUTTER_DIA,LENGTH,Z_LOCATION = 0):
-
- verts = []
- DIV = 36
-
- START_RADIUS = START_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Opp = abs(START_RADIUS - OUTTER_RADIUS)
- Taper_Lentgh = Opp/tan(radians(31));
-
- if Taper_Lentgh > LENGTH:
- Taper_Lentgh = 0
-
- Stright_Length = LENGTH - Taper_Lentgh
-
- Deg_Step = 360.0 /float(DIV)
-
- Row = 0
-
- Lowest_Z_Vert = 0;
-
- Height_Offset = Z_LOCATION
-
-
- #ring
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*START_RADIUS
- y = cos(radians(i*Deg_Step))*START_RADIUS
- z = Height_Offset - 0
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Stright_Length
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*START_RADIUS
- y = cos(radians(i*Deg_Step))*START_RADIUS
- z = Height_Offset - 0
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Taper_Lentgh
- Row += 1
-
-
- return verts,Row,Height_Offset
-
-
-def Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
-
- verts = []
- DIV = 36
-
- INNER_RADIUS = INNER_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Half_Pitch = float(PITCH)/2
- Deg_Step = 360.0 /float(DIV)
- Height_Step = float(PITCH)/float(DIV)
-
- Row = 0
-
- Lowest_Z_Vert = 0;
-
- Height_Offset = Z_LOCATION
-
- Height_Start = Height_Offset
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
- Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
-
- Height_Offset = Z_LOCATION + PITCH
- Cut_off = Z_LOCATION
-
-
- for j in range(1):
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- if z > Cut_off : z = Cut_off
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- if z > Cut_off : z = Cut_off
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- if z > Cut_off : z = Cut_off
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- if z > Cut_off : z = Cut_off
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
-
- for j in range(2):
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z ])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
-
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
-
- return verts,Row,Height_Offset
-
-
-
-def Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
- verts = []
-
- DIV = 36
-
- INNER_RADIUS = INNER_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Half_Pitch = float(PITCH)/2
- Deg_Step = 360.0 /float(DIV)
- Height_Step = float(PITCH)/float(DIV)
-
- NUM_OF_START_THREADS = 4.0
- NUM_OF_END_THREADS = 3.0
- Num = int((HEIGHT- ((NUM_OF_START_THREADS*PITCH) + (NUM_OF_END_THREADS*PITCH) ))/PITCH)
- Row = 0
-
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
-
- Height_Offset = Z_LOCATION
-
- Lowest_Z_Vert = 0;
- FaceStart = len(verts)
-
-
- for j in range(Num):
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- z = Height_Offset - (Height_Step*i)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- z = Height_Offset - (Height_Step*i)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
- return verts,Row,Height_Offset
-
-
-
-def Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
- verts = []
-
- DIV = 36
-
- INNER_RADIUS = INNER_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Half_Pitch = float(PITCH)/2
- Deg_Step = 360.0 /float(DIV)
- Height_Step = float(PITCH)/float(DIV)
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
- Col = 0
- Row = 0
-
- Height_Offset = Z_LOCATION
-
- Tapper_Height_Start = Height_Offset - PITCH - PITCH
-
- Max_Height = Tapper_Height_Start - PITCH
-
- Lowest_Z_Vert = 0;
-
- FaceStart = len(verts)
- for j in range(4):
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- z = max(z,Max_Height)
- Tapper_Radius = OUTTER_RADIUS
- if z < Tapper_Height_Start:
- Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
-
- x = sin(radians(i*Deg_Step))*(Tapper_Radius)
- y = cos(radians(i*Deg_Step))*(Tapper_Radius)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- z = max(z,Max_Height)
- Tapper_Radius = OUTTER_RADIUS
- if z < Tapper_Height_Start:
- Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
-
- x = sin(radians(i*Deg_Step))*(Tapper_Radius)
- y = cos(radians(i*Deg_Step))*(Tapper_Radius)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- z = max(z,Max_Height)
- Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
- if Tapper_Radius > INNER_RADIUS:
- Tapper_Radius = INNER_RADIUS
-
- x = sin(radians(i*Deg_Step))*(Tapper_Radius)
- y = cos(radians(i*Deg_Step))*(Tapper_Radius)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- z = max(z,Max_Height)
- Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
- if Tapper_Radius > INNER_RADIUS:
- Tapper_Radius = INNER_RADIUS
-
- x = sin(radians(i*Deg_Step))*(Tapper_Radius)
- y = cos(radians(i*Deg_Step))*(Tapper_Radius)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
- return verts,Row,Height_Offset,Lowest_Z_Vert
-
-
-
-
-def Create_External_Thread(SHANK_DIA,SHANK_LENGTH,INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT):
-
- verts = []
- faces = []
-
- DIV = 36
-
- Total_Row = 0
- Thread_Len = 0;
-
- Face_Start = len(verts)
- Offset = 0.0;
-
-
- Shank_Verts,Shank_Row,Offset = Create_Shank_Verts(SHANK_DIA,OUTTER_DIA,SHANK_LENGTH,Offset)
- Total_Row += Shank_Row
-
- Thread_Start_Verts,Thread_Start_Row,Offset = Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset)
- Total_Row += Thread_Start_Row
-
-
- Thread_Verts,Thread_Row,Offset = Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT,Offset)
- Total_Row += Thread_Row
-
-
- Thread_End_Verts,Thread_End_Row,Offset,Lowest_Z_Vert = Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset )
- Total_Row += Thread_End_Row
-
-
- verts.extend(Shank_Verts)
- verts.extend(Thread_Start_Verts)
- verts.extend(Thread_Verts)
- verts.extend(Thread_End_Verts)
-
- faces.extend(Build_Face_List_Quads(Face_Start,DIV,Total_Row -1,0))
- faces.extend(Fill_Ring_Face(len(verts)-DIV,DIV,1))
-
- return verts,faces,0.0 - Lowest_Z_Vert
-
-
-##########################################################################################
-##########################################################################################
-## Create Nut
-##########################################################################################
-##########################################################################################
-
-
-def add_Hex_Nut(FLAT,HOLE_DIA,HEIGHT):
- global Global_Head_Height
- global Global_NutRad
-
- verts = []
- faces = []
- HOLE_RADIUS = HOLE_DIA * 0.5
- Half_Flat = FLAT/2
- Half_Height = HEIGHT/2
- TopBevelRadius = Half_Flat - 0.05
-
- Global_NutRad = TopBevelRadius
-
- Row = 0;
- Lowest_Z_Vert = 0.0;
-
- verts.append([0.0,0.0,0.0])
-
-
- FaceStart = len(verts)
- #inner hole
-
- x = sin(radians(0))*HOLE_RADIUS
- y = cos(radians(0))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/6))*HOLE_RADIUS
- y = cos(radians(60/6))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/3))*HOLE_RADIUS
- y = cos(radians(60/3))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/2))*HOLE_RADIUS
- y = cos(radians(60/2))*HOLE_RADIUS
- verts.append([x,y,0.0])
- Row += 1
-
- #bevel
-
- x = sin(radians(0))*TopBevelRadius
- y = cos(radians(0))*TopBevelRadius
- vec1 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/6))*TopBevelRadius
- y = cos(radians(60/6))*TopBevelRadius
- vec2 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/3))*TopBevelRadius
- y = cos(radians(60/3))*TopBevelRadius
- vec3 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/2))*TopBevelRadius
- y = cos(radians(60/2))*TopBevelRadius
- vec4 = Mathutils.Vector([x,y,0.0])
- verts.append([x,y,0.0])
- Row += 1
-
- #Flats
-
- x = tan(radians(0))*Half_Flat
- dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0])
- verts.append([x,Half_Flat,-dvec.length])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
-
-
- x = tan(radians(60/6))*Half_Flat
- dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0])
- verts.append([x,Half_Flat,-dvec.length])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
-
-
- x = tan(radians(60/3))*Half_Flat
- dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0])
- Lowest_Point = -dvec.length
- verts.append([x,Half_Flat,-dvec.length])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
-
- x = tan(radians(60/2))*Half_Flat
- dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0])
- Lowest_Point = -dvec.length
- verts.append([x,Half_Flat,-dvec.length])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
- Row += 1
-
- #down Bits Tri
- x = tan(radians(0))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
-
- x = tan(radians(60/6))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/3))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/2))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
- Lowest_Z_Vert = min(Lowest_Z_Vert,Lowest_Point)
- Row += 1
-
- #down Bits
-
- x = tan(radians(0))*Half_Flat
- verts.append([x,Half_Flat,-Half_Height])
-
- x = tan(radians(60/6))*Half_Flat
- verts.append([x,Half_Flat,-Half_Height])
-
- x = tan(radians(60/3))*Half_Flat
- verts.append([x,Half_Flat,-Half_Height])
-
- x = tan(radians(60/2))*Half_Flat
- verts.append([x,Half_Flat,-Half_Height])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-Half_Height)
- Row += 1
-
-
-
-
- faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
-
-
- Global_Head_Height = HEIGHT
-
- Tvert,tface = Mirror_Verts_Faces(verts,faces,'z',Lowest_Z_Vert)
- verts.extend(Tvert)
- faces.extend(tface)
-
-
- Tvert,tface = Mirror_Verts_Faces(verts,faces,'y')
- verts.extend(Tvert)
- faces.extend(tface)
-
- S_verts,S_faces = SpinDup(verts,faces,360,6,'z')
- return S_verts,S_faces,TopBevelRadius
-
-
-def add_Nylon_Head(OUTSIDE_RADIUS,Z_LOCATION = 0):
- DIV = 36
- verts = []
- faces = []
- Row = 0
-
- INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.25/4.75))
- EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
- RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
- OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
-
-
- FaceStart = len(verts)
-
- Start_Height = 0 - 3
- Height_Offset = Z_LOCATION
- Lowest_Z_Vert = 0
-
- x = INNER_HOLE
- z = (Height_Offset - OVER_ALL_HEIGTH) + EDGE_THICKNESS
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- x = INNER_HOLE
- z = (Height_Offset - OVER_ALL_HEIGTH)
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
-
- for i in range(180,80,-10):
- x = sin(radians(i))*RAD1
- z = cos(radians(i))*RAD1
- verts.append([(OUTSIDE_RADIUS-RAD1)+x,0.0,((Height_Offset - OVER_ALL_HEIGTH)+RAD1)+z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
-
- x = OUTSIDE_RADIUS - 0
- z = Height_Offset
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV,1))
-
- return Move_Verts_Up_Z(sVerts,0),faces,Lowest_Z_Vert
-
-
-
-def add_Nylon_Part(OUTSIDE_RADIUS,Z_LOCATION = 0):
- DIV = 36
- verts = []
- faces = []
- Row = 0
-
- INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75))
- EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
- RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
- OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
- PART_THICKNESS = OVER_ALL_HEIGTH - EDGE_THICKNESS
- PART_INNER_HOLE = (OUTSIDE_RADIUS * (2.5/4.75))
-
- FaceStart = len(verts)
-
- Start_Height = 0 - 3
- Height_Offset = Z_LOCATION
- Lowest_Z_Vert = 0
-
-
- x = INNER_HOLE + EDGE_THICKNESS
- z = Height_Offset
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- x = PART_INNER_HOLE
- z = Height_Offset
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- x = PART_INNER_HOLE
- z = Height_Offset - PART_THICKNESS
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- x = INNER_HOLE + EDGE_THICKNESS
- z = Height_Offset - PART_THICKNESS
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV,1))
-
- return sVerts,faces,0 - Lowest_Z_Vert
-
-
-
-def Nut_Mesh():
-
- verts = []
- faces = []
- Head_Verts = []
- Head_Faces= []
-
- Face_Start = len(verts)
- Thread_Verts,Thread_Faces,New_Nut_Height = Create_Internal_Thread(Minor_Dia.val,Major_Dia.val,Pitch.val,Hex_Nut_Height.val,Crest_Percent.val,Root_Percent.val,1)
- verts.extend(Thread_Verts)
- faces.extend(Copy_Faces(Thread_Faces,Face_Start))
-
- Face_Start = len(verts)
- Head_Verts,Head_Faces,Lock_Nut_Rad = add_Hex_Nut(Hex_Nut_Flat_Distance.val,Major_Dia.val,New_Nut_Height)
- verts.extend((Head_Verts))
- faces.extend(Copy_Faces(Head_Faces,Face_Start))
-
- LowZ = 0 - New_Nut_Height
-
- if Nut_Type['LOCK'][0].val:
- Face_Start = len(verts)
- Nylon_Head_Verts,Nylon_Head_faces,LowZ = add_Nylon_Head(Lock_Nut_Rad,0-New_Nut_Height)
- verts.extend((Nylon_Head_Verts))
- faces.extend(Copy_Faces(Nylon_Head_faces,Face_Start))
-
- Face_Start = len(verts)
- Nylon_Verts,Nylon_faces,Temp_LowZ = add_Nylon_Part(Lock_Nut_Rad,0-New_Nut_Height)
- verts.extend((Nylon_Verts))
- faces.extend(Copy_Faces(Nylon_faces,Face_Start))
-
-
- return Move_Verts_Up_Z(verts,0 - LowZ),faces
-
-
-
-##################################################################################################
-
-
-def Create_Nut():
-
- verts = []
- faces = []
-
-
- if Error_Check() :
- return
-
-
- verts, faces = Nut_Mesh()
- Add_Mesh_To_Scene('Nut', verts, faces)
-
-
-##################################################################################################
-
-
-def Create_Bolt():
- verts = []
- faces = []
-
-
- if Error_Check() :
- return
-
- verts, faces = MakeBolt()
- Add_Mesh_To_Scene('Bolt', verts, faces)
-
-
-
-def Remove_Doubles_From_Mesh(verts,faces):
- Ret_verts = []
- Ret_faces = []
-
- is_editmode = Window.EditMode() # Store edit mode state
- if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode.
-
- Temp_mesh = Mesh.New('MeshTemp') # create a new mesh
-
- Temp_mesh.verts.extend(verts) # add vertices to mesh
- Temp_mesh.faces.extend(faces) # add faces to the mesh (also adds edges)
-
- scn = Scene.GetCurrent() # link object to current scene
- Temp_Object = scn.objects.new(Temp_mesh, 'ObjectTemp')
-
- Temp_mesh.remDoubles(0.010)
- Temp_mesh.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale]))
- Ret_verts[:] = [v.co for v in Temp_mesh.verts]
- Ret_faces[:] = [ [v.index for v in f] for f in Temp_mesh.faces]
-
- #delete temp mesh
- scn.objects.unlink(Temp_Object)
- scn.update(0)
-
- if is_editmode: Window.EditMode(1)
- return Ret_verts,Ret_faces
-
-
-
-def Add_Mesh_To_Scene(name, verts, faces):
-
- scn = Scene.GetCurrent()
- if scn.lib: return
- ob_act = scn.objects.active
-
- is_editmode = Window.EditMode()
-
- cursor = Window.GetCursorPos()
- quat = None
-
- if is_editmode or Blender.Get('add_view_align'): # Aligning seems odd for editmode, but blender does it, oh well
- try: quat = Blender.Mathutils.Quaternion(Window.GetViewQuat())
- except: pass
-
-
- # Exist editmode for non mesh types
- if ob_act and ob_act.type != 'Mesh' and is_editmode:
- EditMode(0)
-
- # We are in mesh editmode
- if Window.EditMode():
- me = ob_act.getData(mesh=1)
-
- if me.multires:
- error_txt = 'Error%t|Unable to complete action with multires enabled'
- Blender.Draw.PupMenu(error_txt)
- print error_txt
- return
-
- #Don't want to remove doubles and scale the existing
- # mesh so we need to get the verts and the faces from
- # a mesh that has been scaled.
- verts,faces = Remove_Doubles_From_Mesh(verts, faces)
-
- # Add to existing mesh
- # must exit editmode to modify mesh
- Window.EditMode(0)
-
- me.sel = False
-
- vert_offset = len(me.verts)
- face_offset = len(me.faces)
-
-
- # transform the verts
- txmat = Blender.Mathutils.TranslationMatrix(Blender.Mathutils.Vector(cursor))
- if quat:
- mat = quat.toMatrix()
- mat.invert()
- mat.resize4x4()
- txmat = mat * txmat
-
- txmat = txmat * ob_act.matrixWorld.copy().invert()
-
-
- me.verts.extend(verts)
- # Transform the verts by the cursor and view rotation
- me.transform(txmat, selected_only=True)
-
- if vert_offset:
- me.faces.extend([[i+vert_offset for i in f] for f in faces])
- else:
- # Mesh with no data, unlikely
- me.faces.extend(faces)
- else:
-
- # Object mode add new
- me = Mesh.New(name)
- me.verts.extend(verts)
- me.faces.extend(faces)
-
-
- me.sel = True
-
- # Object creation and location
- scn.objects.selected = []
- ob_act = scn.objects.new(me, name)
-
- me.remDoubles(0.010)
- me.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale]))
-
- scn.objects.active = ob_act
-
- if quat:
- mat = quat.toMatrix()
- mat.invert()
- mat.resize4x4()
- ob_act.setMatrix(mat)
-
- ob_act.loc = cursor
-
- me.calcNormals()
-
- if is_editmode or Blender.Get('add_editmode'):
- Window.EditMode(1)
-
- Blender.Redraw(-1)#Redraw all
-
-##################################################################################################
-
-
-
-def Load_Preset():
-
- global Preset_Menu
- global Shank_Dia
- global Shank_Length
- global Thread_Length
- global Major_Dia
- global Minor_Dia
- global Pitch
- global Crest_Percent
- global Root_Percent
- global Allen_Bit_Flat_Distance
- global Allen_Bit_Depth
- global Head_Height
- global Hex_Head_Flat_Distance
- global Head_Dia
- global Dome_Head_Dia
- global Pan_Head_Dia
- global Philips_Bit_Dia
- global Phillips_Bit_Depth
- global Cap_Head_Height
-
- global Hex_Nut_Height
- global Hex_Nut_Flat_Distance
-
-
- if Preset_Menu.val == 1 : #M3
- Shank_Dia.val = 3.0
- #Pitch.val = 0.5 #Coarse
- Pitch.val = 0.35 #Fine
- Crest_Percent.val = 10
- Root_Percent.val = 10
- Major_Dia.val = 3.0
- Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
- Hex_Head_Flat_Distance.val = 5.5
- Hex_Head_Height.val = 2.0
- Cap_Head_Dia.val = 5.5
- Cap_Head_Height.val = 3.0
- Allen_Bit_Flat_Distance.val = 2.5
- Allen_Bit_Depth.val = 1.5
- Pan_Head_Dia.val = 5.6
- Dome_Head_Dia.val = 5.6
- Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
- Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
- Hex_Nut_Height.val = 2.4
- Hex_Nut_Flat_Distance.val = 5.5
- Thread_Length.val = 6
- Shank_Length.val = 0.0
-
-
- if Preset_Menu.val == 2 : #M4
- Shank_Dia.val = 4.0
- #Pitch.val = 0.7 #Coarse
- Pitch.val = 0.5 #Fine
- Crest_Percent.val = 10
- Root_Percent.val = 10
- Major_Dia.val = 4.0
- Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
- Hex_Head_Flat_Distance.val = 7.0
- Hex_Head_Height.val = 2.8
- Cap_Head_Dia.val = 7.0
- Cap_Head_Height.val = 4.0
- Allen_Bit_Flat_Distance.val = 3.0
- Allen_Bit_Depth.val = 2.0
- Pan_Head_Dia.val = 8.0
- Dome_Head_Dia.val = 8.0
- Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
- Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
- Hex_Nut_Height.val = 3.2
- Hex_Nut_Flat_Distance.val = 7.0
- Thread_Length.val = 8
- Shank_Length.val = 0.0
-
-
- if Preset_Menu.val == 3 : #M5
- Shank_Dia.val = 5.0
- #Pitch.val = 0.8 #Coarse
- Pitch.val = 0.5 #Fine
- Crest_Percent.val = 10
- Root_Percent.val = 10
- Major_Dia.val = 5.0
- Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
- Hex_Head_Flat_Distance.val = 8.0
- Hex_Head_Height.val = 3.5
- Cap_Head_Dia.val = 8.5
- Cap_Head_Height.val = 5.0
- Allen_Bit_Flat_Distance.val = 4.0
- Allen_Bit_Depth.val = 2.5
- Pan_Head_Dia.val = 9.5
- Dome_Head_Dia.val = 9.5
- Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
- Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
- Hex_Nut_Height.val = 4.0
- Hex_Nut_Flat_Distance.val = 8.0
- Thread_Length.val = 10
- Shank_Length.val = 0.0
-
-
- if Preset_Menu.val == 4 : #M6
- Shank_Dia.val = 6.0
- #Pitch.val = 1.0 #Coarse
- Pitch.val = 0.75 #Fine
- Crest_Percent.val = 10
- Root_Percent.val = 10
- Major_Dia.val = 6.0
- Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
- Hex_Head_Flat_Distance.val = 10.0
- Hex_Head_Height.val = 4.0
- Cap_Head_Dia.val = 10.0
- Cap_Head_Height.val = 6.0
- Allen_Bit_Flat_Distance.val = 5.0
- Allen_Bit_Depth.val = 3.0
- Pan_Head_Dia.val = 12.0
- Dome_Head_Dia.val = 12.0
- Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
- Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
- Hex_Nut_Height.val = 5.0
- Hex_Nut_Flat_Distance.val = 10.0
- Thread_Length.val = 12
- Shank_Length.val = 0.0
-
-
- if Preset_Menu.val == 5 : #M8
- Shank_Dia.val = 8.0
- #Pitch.val = 1.25 #Coarse
- Pitch.val = 1.00 #Fine
- Crest_Percent.val = 10
- Root_Percent.val = 10
- Major_Dia.val = 8.0
- Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
- Hex_Head_Flat_Distance.val = 13.0
- Hex_Head_Height.val = 5.3
- Cap_Head_Dia.val = 13.5
- Cap_Head_Height.val = 8.0
- Allen_Bit_Flat_Distance.val = 6.0
- Allen_Bit_Depth.val = 4.0
- Pan_Head_Dia.val = 16.0
- Dome_Head_Dia.val = 16.0
- Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
- Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
- Hex_Nut_Height.val = 6.5
- Hex_Nut_Flat_Distance.val = 13.0
- Thread_Length.val = 16
- Shank_Length.val = 0.0
-
- if Preset_Menu.val == 6 : #M10
- Shank_Dia.val = 10.0
- #Pitch.val = 1.5 #Coarse
- Pitch.val = 1.25 #Fine
- Crest_Percent.val = 10
- Root_Percent.val = 10
- Major_Dia.val = 10.0
- Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
- Hex_Head_Flat_Distance.val = 17.0
- Hex_Head_Height.val = 6.4
- Cap_Head_Dia.val = 16.0
- Cap_Head_Height.val = 10.0
- Allen_Bit_Flat_Distance.val = 8.0
- Allen_Bit_Depth.val = 5.0
- Pan_Head_Dia.val = 20.0
- Dome_Head_Dia.val = 20.0
- Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
- Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
- Hex_Nut_Height.val = 8.0
- Hex_Nut_Flat_Distance.val = 17.0
- Thread_Length.val = 20
- Shank_Length.val = 0.0
-
-
- if Preset_Menu.val == 7 : #M12
- #Pitch.val = 1.75 #Coarse
- Pitch.val = 1.50 #Fine
- Crest_Percent.val = 10
- Root_Percent.val = 10
- Major_Dia.val = 12.0
- Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
- Hex_Head_Flat_Distance.val = 19.0
- Hex_Head_Height.val = 7.5
- Cap_Head_Dia.val = 18.5
- Cap_Head_Height.val = 12.0
- Allen_Bit_Flat_Distance.val = 10.0
- Allen_Bit_Depth.val = 6.0
- Pan_Head_Dia.val = 24.0
- Dome_Head_Dia.val = 24.0
- Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
- Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
- Hex_Nut_Height.val = 10.0
- Hex_Nut_Flat_Distance.val = 19.0
- Shank_Dia.val = 12.0
- Shank_Length.val = 33.0
- Thread_Length.val = 32.0
-
-##############################################################################################
-
-def Test():
- verts = []
- faces = []
-
- if Error_Check() :
- return
-
- verts, faces = MakeBolt()
-
- Add_Mesh_To_Scene("TestBolt", verts,faces)
-
- Window.Redraw(-1)
-
-
-
-
-def event(evt, val): # the function to handle input events
-
- if evt == Draw.ESCKEY:
- Draw.Exit() # exit when user presses ESC
- return
-
-
-def button_event(evt): # the function to handle Draw Button events
-
- if evt == On_Exit_Click:
- Draw.Exit() # exit when user presses ESC
- return
-
- if evt == On_Test_Click:
- Test()
- Draw.Redraw(1)
-
- if evt == On_Preset_Click:
- Load_Preset()
- Draw.Redraw(1)
-
- if evt == On_Create_Click:
- if Model_Type['BOLT'][0].val:
- Create_Bolt()
- if Model_Type['NUT'][0].val:
- Create_Nut()
- Draw.Redraw(1)
-
- elif (evt in [On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click]):
- for k in Head_Type.iterkeys():
- if Head_Type[k][1]!=evt:
- Head_Type[k][0].val=0
- else:
- Head_Type[k][0].val=1
- Draw.Redraw(1)
-
- elif (evt in [On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click]):
- for k in Bit_Type.iterkeys():
- if Bit_Type[k][1]!=evt:
- Bit_Type[k][0].val=0
- else:
- Bit_Type[k][0].val=1
- Draw.Redraw(1)
-
- elif (evt in [On_Model_Bolt_Click,On_Model_Nut_Click]):
- for k in Model_Type.iterkeys():
- if Model_Type[k][1]!=evt:
- Model_Type[k][0].val=0
- else:
- Model_Type[k][0].val=1
- Draw.Redraw(1)
-
- elif (evt in [On_Hex_Nut_Click,On_Lock_Nut_Click]):
- for k in Nut_Type.iterkeys():
- if Nut_Type[k][1]!=evt:
- Nut_Type[k][0].val=0
- else:
- Nut_Type[k][0].val=1
- Draw.Redraw(1)
-
-#####################################################################################
-
-
-def Draw_Border(X1,Y1,X2,Y2): # X1,Y1 = Top Left X2,Y2 = Bottom Right
- INDENT = 3
-
- BGL.glColor3f(1.0,1.0,1.0)
- BGL.glBegin(BGL.GL_LINES)
- BGL.glVertex2i(X1+INDENT,Y1-INDENT) #top line
- BGL.glVertex2i(X2-INDENT,Y1-INDENT)
-
- BGL.glVertex2i(X1+INDENT,Y1-INDENT) #left line
- BGL.glVertex2i(X1+INDENT,Y2+INDENT)
- BGL.glEnd()
-
- BGL.glColor3f(0.5,0.5,0.5)
- BGL.glBegin(BGL.GL_LINES)
- BGL.glVertex2i(X2-INDENT,Y1-INDENT) #Right line
- BGL.glVertex2i(X2-INDENT,Y2+INDENT)
-
- BGL.glVertex2i(X1+INDENT,Y2+INDENT) #bottom line
- BGL.glVertex2i(X2-INDENT,Y2+INDENT)
- BGL.glEnd()
-
-
-
-
-def Create_Tab(X1,Y1,X2,Y2,Title,Buttons): # X1,Y1 = Top Left X2,Y2 = Bottom Right
-
- BIT_BUTTON_WIDTH = 55
- BIT_BUTTON_HEIGHT = 18
- TITLE_HEIGHT = 15
- INDENT = 6
- BUTTON_GAP = 4
-
- BGL.glColor3f(0.75, 0.75, 0.75)
- BGL.glRecti(X1,Y1,X2,Y2)
-
- Draw_Border(X1,Y1,X2,Y2);
-
- BGL.glColor3f(0.0,0.0,0.0)
- BGL.glRasterPos2d(X1+INDENT,Y1 - TITLE_HEIGHT)
- Draw.Text(Title)
-
- Button_X = X1 + INDENT
- Button_Y = Y1 - TITLE_HEIGHT - BIT_BUTTON_HEIGHT - 8
-
- #Nut_Number_X = Nut_Button_X
- #Nut_Number_Y = Nut_Button_Y - 25
- if (Buttons != 0):
- key= Buttons.keys()
- for k in key:
- Buttons[k][0]= Draw.Toggle(k,Buttons[k][1],Button_X,Button_Y, BIT_BUTTON_WIDTH,BIT_BUTTON_HEIGHT,Buttons[k][0].val,Buttons[k][2])
- Button_X += BIT_BUTTON_WIDTH + BUTTON_GAP
-
-
-
-def Dispaly_Title_Bar(Y_POS,CONTROL_HEIGHT):
- CONTROL_WIDTH = 250
- Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS -CONTROL_HEIGHT,"Bolt Factory V2.02",Model_Type)
-
-
-
-def Dispaly_Preset_Tab(Y_POS,CONTROL_HEIGHT):
- CONTROL_WIDTH = 250
- BUTTON_Y_OFFSET = 40
-
- Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Preset",0)
-
- name = "M3%x1|M4%x2|M5%x3|M6%x4|M8%x5|M10%x6|M12%x7"
-
- global Preset_Menu
- Preset_Menu = Draw.Menu(name,No_Event,9,Y_POS-BUTTON_Y_OFFSET,50,18, Preset_Menu.val, "Predefined metric screw sizes.")
- Draw.Button("Apply",On_Preset_Click,150,Y_POS-BUTTON_Y_OFFSET,55,18,"Apply the preset screw sizes.")
-
-
-def Dispaly_Bit_Tab(Y_POS,CONTROL_HEIGHT):
-
- CONTROL_WIDTH = 250
- NUMBER_HEIGHT = 18
- NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
-
- Bit_Number_X = 3+3+3
- Bit_Number_Y = Y_POS - 64
-
- Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Bit Type",Bit_Type)
-
- if Bit_Type['NONE'][0].val:
- DoNothing = 1;
-
- elif Bit_Type['ALLEN'][0].val:
- global Allen_Bit_Depth
- Allen_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Allen_Bit_Depth.val, 0,100, '')
- Bit_Number_Y -= NUMBER_HEIGHT
- global Allen_Bit_Flat_Distance
- Allen_Bit_Flat_Distance = Draw.Number('Flat Dist: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH,NUMBER_HEIGHT,Allen_Bit_Flat_Distance.val, 0,100, '')
- Bit_Number_Y -= NUMBER_HEIGHT
-
- elif Bit_Type['PHILLIPS'][0].val:
- global Phillips_Bit_Depth
- Phillips_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Phillips_Bit_Depth.val, 0,100, '')
- Bit_Number_Y -= NUMBER_HEIGHT
- global Philips_Bit_Dia
- Philips_Bit_Dia = Draw.Number('Bit Dia: ',No_Event,Bit_Number_X,Bit_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Philips_Bit_Dia.val, 0,100, '')
- Bit_Number_Y -= NUMBER_HEIGHT
-
-
-
-def Dispaly_Shank_Tab(Y_POS,CONTROL_HEIGHT):
-
- CONTROL_WIDTH = 250
- NUMBER_HEIGHT = 18
- NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
-
- Number_X = 3+3+3
- Number_Y_Pos = Y_POS - 40
-
- Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Shank",0)
-
- global Shank_Length
- Shank_Length = Draw.Number('Shank Length: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Length.val, 0,MAX_INPUT_NUMBER, 'some text tip')
- Number_Y_Pos -= NUMBER_HEIGHT
-
- global Shank_Dia
- Shank_Dia = Draw.Number('Shank Dia: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Dia.val, 0,MAX_INPUT_NUMBER, 'some text tip')
- Number_Y_Pos -= NUMBER_HEIGHT
-
-
-
-def Dispaly_Thread_Tab(Y_POS,CONTROL_HEIGHT):
-
- CONTROL_WIDTH = 250
- NUMBER_HEIGHT = 18
- NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
-
-
- Number_X = 3+3+3
- Number_Y_Pos = Y_POS - 40
-
- Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Thread",0)
-
- global Thread_Length
- if Model_Type['BOLT'][0].val:
- Thread_Length = Draw.Number('Thread Length: ',No_Event, Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Thread_Length.val, 0,MAX_INPUT_NUMBER, '')
- Number_Y_Pos -= NUMBER_HEIGHT
-
- global Major_Dia
- Major_Dia = Draw.Number('Major Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Major_Dia.val, 0,MAX_INPUT_NUMBER, '')
- Number_Y_Pos -= NUMBER_HEIGHT
-
- global Minor_Dia
- Minor_Dia = Draw.Number('Minor Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Minor_Dia.val, 0,MAX_INPUT_NUMBER, '')
- Number_Y_Pos -= NUMBER_HEIGHT
-
- global Pitch
- Pitch = Draw.Number('Pitch: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Pitch.val, 0.1,7.0, '')
- Number_Y_Pos -= NUMBER_HEIGHT
-
- global Crest_Percent
- Crest_Percent = Draw.Number('Crest %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Crest_Percent.val, 1,90, '')
- Number_Y_Pos -= NUMBER_HEIGHT
-
- global Root_Percent
- Root_Percent = Draw.Number('Root %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Root_Percent.val, 1,90, '')
- Number_Y_Pos -= NUMBER_HEIGHT
-
-
-
-
-def Dispaly_Head_Tab(Y_POS,CONTROL_HEIGHT):
-
- CONTROL_WIDTH = 250
- NUMBER_HEIGHT = 18
- NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
-
- Head_Number_X = 3+3+3
- Head_Number_Y = Y_POS - 64
-
- Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Head Type",Head_Type)
-
- if Head_Type['HEX'][0].val:
- global Hex_Head_Height
- Hex_Head_Height = Draw.Number('Head Height: ',No_Event,Head_Number_X ,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Height.val, 0,100, '')
- Head_Number_Y -= NUMBER_HEIGHT
- global Hex_Head_Flat_Distance
- Hex_Head_Flat_Distance = Draw.Number('Head Hex Flat Distance ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
- Head_Number_Y -= NUMBER_HEIGHT
-
- elif Head_Type['CAP'][0].val:
- global Cap_Head_Height
- Cap_Head_Height = Draw.Number('Head Height: ',No_Event, Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Height.val, 0,100, '')
- Head_Number_Y -= NUMBER_HEIGHT
- global Cap_Head_Dia
- Cap_Head_Dia = Draw.Number('Head Dia ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
- Head_Number_Y -= NUMBER_HEIGHT
-
- elif Head_Type['DOME'][0].val:
- global Dome_Head_Dia
- Dome_Head_Dia = Draw.Number(' Dome Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Dome_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
- Head_Number_Y -= NUMBER_HEIGHT
-
- elif Head_Type['PAN'][0].val:
- global Pan_Head_Dia
- Pan_Head_Dia = Draw.Number('Pan Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Pan_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
- Head_Number_Y -= NUMBER_HEIGHT
-
-
-
-
-def Dispaly_Nut_Tab(Y_POS,CONTROL_HEIGHT):
-
- CONTROL_WIDTH = 250
- NUMBER_HEIGHT = 18
- NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
-
- Nut_Number_X = 3+3+3
- Nut_Number_Y = Y_POS - 64
-
- Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Nut Type",Nut_Type)
-
- #if Nut_Type['HEX'][0].val:
- global Hex_Nut_Height
- Hex_Nut_Height = Draw.Number('Nut Height: ',No_Event,Nut_Number_X ,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Height.val, 0,MAX_INPUT_NUMBER, '')
- Nut_Number_Y -= NUMBER_HEIGHT
- global Hex_Nut_Flat_Distance
- Hex_Nut_Flat_Distance = Draw.Number('Nut Flat Distance ',No_Event,Nut_Number_X,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
- Nut_Number_Y -= NUMBER_HEIGHT
-
-
-def Dispaly_Bolt_Tab():
-
- Dispaly_Shank_Tab(284,66)
- Dispaly_Head_Tab(374,90)
- Dispaly_Bit_Tab(464,90)
-
-
-##########################################################################################
-
-def gui(): # the function to draw the screen
-
- CONTROL_WIDTH = 250
-
- BGL.glClearColor(0.6, 0.6, 0.6, 1.0)
- BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
-
- BGL.glColor3f(0.75, 0.75, 0.75)
- BGL.glRecti(3,30,CONTROL_WIDTH,3)
-
- Dispaly_Title_Bar(514,50);
-
- if Model_Type['BOLT'][0].val:
- Dispaly_Bolt_Tab();
-
- if Model_Type['NUT'][0].val:
- Dispaly_Nut_Tab(464,246);
-
- Dispaly_Thread_Tab(218,138)
-
- Dispaly_Preset_Tab(80,50)
-
- Draw.PushButton("Create",On_Create_Click,6,8,55,18,"Create Bolt")
- Draw.Button("Exit",On_Exit_Click,6+55+4,8,55,18)
-
-# Draw.Button("Test",On_Test_Click,150,10,55,20)
-
-Load_Preset()
-Draw.Register(gui, event, button_event) # registering the 3 callbacks
diff --git a/release/scripts/wizard_landscape_ant.py b/release/scripts/wizard_landscape_ant.py
deleted file mode 100644
index 405c06432ca..00000000000
--- a/release/scripts/wizard_landscape_ant.py
+++ /dev/null
@@ -1,2148 +0,0 @@
-#!BPY
-"""
-Name: 'Landscape Generator (A.N.T)'
-Blender: 248
-Group: 'Wizards'
-Tip: 'Create landscape mesh.'
-"""
-
-__author__ = "Jimmy Hazevoet"
-__url__ = ('http://wiki.blender.org/index.php/Scripts/Manual/Wizards/ANTLandscape','elysiun')
-__version__ = "v.1.05 03-2007"
-__bpydoc__ = """\
-
-Another Noise Tool 'Landscape' v.1.05
-
-This script uses noise functions to create a terrain from a grid mesh.
-
-Usage:
-
-Make new terrain: press the "Add New Grid" button, change some noise settings and press the "Update" button.
-
-Work on previous made grid: select the grid/terrain in the 3D view, and press the "Assign" button.
-
-Tip: use a low resolution grid mesh and add some Multires levels for detail
-
-Note: when using Multires materials can get weird,
-only apply materials when your terrain is ready, or not use Multires.
-
-This Script creates a landscape mesh.
-Press the Auto button when you start the script.
-Then the Generate Button & read it's tooltip.
-The mesh created is average 16000 verts.
-To me the mesh appears quite small in the 3d view.
-Just Press S in the 3d view to scale it up.
-This saves overhead drawing the Mesh.
-
-Known Issues:
-If the mesh is not drawn in the 3d view first time,
-Move your mouse to the 3d view, or press the button again.
-
-Not really an issue, more to be aware.
-Due to the complex nature & design of the script, it only creates one mesh at a time.
-When you press Generate or Reset,
-Even if you have Closed then Opened the script or .blend file,
-The mesh Will be Overwritten.
-To create Multiple Landscapes you Must Re-Name or save the Mesh
-in Blender's F7 menu Links & Materials Panel.
-
-Readme:
-v.1.04:
-_ New G.U.I.
-_ New noise types like:
-Double_Terrain,
-StatsByAlt_Terrain,
-slickRock,
-ditorted_heteroTerrain,
-vlNoise_turbulence,
-and many more.
-
-New fractalized Effect functions.
-Effect types such as: gradient,
-waves and bumps, dome, piramide,
-squares, grid, shattered rocks,
-lunar, and many more.
-
-Bias types: Sin, Cos, Tri, Saw,
-and Default(no bias).
-
-For example the 'Rings' effect
-with 'Sin Bias' makes 'Rings'
-and 'Default Bias' makes 'Dome'.
-The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible,
--1.0=noise, 0.0=average, 1.0=effect
-this slider controls also the 'Warp amount' if mix type 'Warp' is selected.
-
-Image effect: mix image with noise
-_ IPOCurve Filter: use Ipo curve to filter terrain height.
-I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that)
-the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible.
-Usage:
-Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times),
-move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want,
-Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely.
-(use the 'Pin' option to keep the curves visible while other objects are selected)
-Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve.
-A curve filter is very versatile when it comes to 'height' filtering.
-
-_ PreView in UV/Image Editor Window:
-The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga'
-you have to select 'ANTview_size.tga' in the UV/Image Editor Window
-now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled),
-! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) !
-
-_ VertexColours: use any image as colour gradient.
-This function actualy uses one 'row' of pixels from a image to produce the color gradient,
-Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top.
-you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result)
-Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel !
-
-_ Mesh Tiles: Create large scale terrains.
-
-_ Vertices Selection: select flat areas.
-
-_ Keyboard HotKeys:
-SPACE = Update mesh.
-R = Randomise.
-V = Redraw preview.
-
-_ and more...
-
-"""
-
-
-
-
-###
-#
-# Alt+P to start script.
-#
-###
-# scroll down to see info about updates
-##
-################################################################################################################
-# Another Noise Tool 'Landscape'
-# Jimmy Hazevoet
-# license: Do whatever you want with it.
-################################################################################################################
-
-################################################################################################################
-# v.1.04:
-#
-# _ New G.U.I.
-# _ New noise types like: Double_Terrain, StatsByAlt_Terrain, slickRock, ditorted_heteroTerrain, vlNoise_turbulence, and many more.
-# _ New fractalized Effect functions.
-# Effect types such as: gradient, waves and bumps, dome, piramide, squares, grid, shattered rocks, lunar, and many more.
-# Bias types: Sin, Cos, Tri, Saw, and Default(no bias).
-# For example the 'Rings' effect with 'Sin Bias' makes 'Rings' and 'Default Bias' makes 'Dome'.
-# _ The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, -1.0=noise, 0.0=average, 1.0=effect
-# this slider controls also the 'Warp amount' if mix type 'Warp' is selected.
-# _ Image effect: mix image with noise
-# _ IPOCurve Filter: use Ipo curve to filter terrain height.
-# I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that)
-# the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible.
-# Usage:
-# Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times),
-# move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want,
-# Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely.
-# (use the 'Pin' option to keep the curves visible while other objects are selected)
-# Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve.
-# A curve filter is very versatile when it comes to 'height' filtering.
-# _ PreView in UV/Image Editor Window:
-# The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga'
-# you have to select 'ANTview_size.tga' in the UV/Image Editor Window
-# now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled),
-# ! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) !
-# _ VertexColours: use any image as colour gradient.
-# This function actualy uses one 'row' of pixels from a image to produce the color gradient,
-# Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top.
-# you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result)
-# Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel !
-# _ Mesh Tiles: Create large scale terrains.
-# _ Vertices Selection: select flat areas.
-# _ Keyboard HotKeys:
-# SPACE = Update mesh.
-# R = Randomise.
-# V = Redraw preview.
-# _ and more...
-################################################################################################################
-
-################################################################################################################
-# BugFix: Sept./2006 v.1.04a
-#-----------------------------
-# _Image Effect did not worked well with tiled mesh. Fixed (now use Freq. and Loc. buttons to scale and position image).
-#
-################################################################################################################
-
-
-################################################################################################################
-# UPDATE: v.1.05 03-2007
-#---------------------------------------------------------------------------------------------------------------
-#
-# _ New: Save and Load function, save your settings to a .ant file.
-# __NOTE: when saving/loading settings to/from a file,
-# make sure the filename/path is not too long!
-# __HOTKEY__ Load from file: L
-# __HOTKEY__ Save to file : S
-#
-# _ New mesh code, uses Mesh instead of NMesh,
-# this gives a small speed improvement and alows you to use Multires.
-#
-# Usage: Select a Grid/Terrain mesh and hit the Assign button, now you can work on it, when ready you assign another.
-#
-# _ New: 'Musgrave' noise types, 'Random noise' and 'Constant' in 'Effects' section.
-# _ New: 'Custom Effect', write custom formulae ( x,y, a,b, from math import *, from Blender.Noise import * )
-# _ New: 'Custom Height Filter', write custom formulae ( x,y, h, a,b, from math import *, from Blender.Noise import * )
-# _ New: 'Change Filter Order', Toggle: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff
-#
-# _ If you want to make a tiled terrain, you need to set the coordinates to "WorldSpace" or "Center at Cursor" (in G.U.I.Noise panel),
-# create and place the grid meshes. now one by one select, assign and update, you may need to adjust the "EdgeFalloff" size.
-#
-# WARNING!: when using Multires, materials can get weird (?), so apply materials when your terrain is finnished.
-#
-###############################################################################################################
-
-
-###############################################################################################################
-#
-## Execute Script: Alt P
-#
-
-
-import Blender
-from Blender import *
-from math import *
-from Blender.Noise import *
-from Blender.Draw import *
-from Blender.BGL import *
-from Blender import Image
-import string
-from string import strip
-import BPyMathutils
-from BPyMathutils import genrand
-from random import choice
-scene = Scene.GetCurrent()
-
-###---------------------------------------------------------------------------
-
-CurVersion = 'A.N.T.Landscape v.1.05'
-
-##---------------------------------------------------------------------------
-# Customise default settings: ----------------------------------------------
-
-# Names:
-antfilename = 'Terrain' # Default filename
-previewname = Create('') # Default preview Image name
-DefaultIpoName = '' # Default Ipo DataBlock name (for height filter)
-# G.U.I.:
-FullScreen = Create( 0 ) # FullScreen on/off
-# gui colors:
-ledcolors = [ [1.0,0.498,0.498], [1.0,0.698,0.498], [1.0,0.898,0.498], [0.898,1.0,0.498], [0.698,1.0,0.498], [0.498,1.0,0.498], [0.498,1.0,0.698], [0.498,1.0,0.898], [0.600,0.918,1.0], [0.6,0.757,1.0], [0.6,0.6,1.0], [0.757,0.6,1.0], [0.898,0.498,1.0], [1.0,0.498,0.898] ]
-#ledcolor = [ 1.0, 0.5, 0.0 ]
-lightgrey = [ 0.76, 0.76, 0.76 ] # gui col.
-grey = [ 0.6, 0.6, 0.6 ] # panel col.
-background = [ 0.7, 0.7, 0.7, 1.0 ] # background col.
-black = [ 0.0, 0.0, 0.0 ] # text col.
-white = [ 1.0, 1.0, 1.0 ]
-# gui size
-size_x = 320 # gui x size
-size_y = 280 # gui y size
-# tabs
-guitabs = [ Create( 1 ), Create( 0 ), Create( 0 ), Create( 0 ), Create( 0 ) ] # gui Tabs
-# How long does it take to generate a mesh or image ?
-print_time = 0 # 1 = Print time in console.
-
-# end customise. ----------------------------------------------------------
-##--------------------------------------------------------------------------
-###--------------------------------------------------------------------------
-####--------------------------------------------------------------------------
-##---------------------------------------------------------------------------
-
-dirpath=Blender.sys.dirname(Blender.Get('filename'))
-fname=dirpath.replace('\\','/')+'/' + antfilename + '.ant'
-txtFile = Create( fname )
-
-###---------------------------------------------------------------------------
-columns = 10 # gui columns
-rows = 13 # gui rows
-actob = [] # active object
-actme = [] # active mesh
-ipoblockname=''
-thiscurve=[]
-selectedcurve=0
-phi=3.14159265359
-# events
-App_Evt = 144
-New_Evt = 166
-SelFile_Evt = 71
-LoadFile_Evt = 72
-SaveFile_Evt = 73
-UseMe_Evt = 74
-No_Evt = 1
-Btn_Evt = 2
-Msh_Evt = 12
-Upd_Evt = 3
-Rndm_Evt = 4
-Load_Evt = 5
-Sel_Evt = 6
-Save_Evt = 7
-Rend_Evt = 8
-End_Evt = 9
-Scrn_Evt = 15
-Im_Evt = 16
-gt0_Evt = 20
-gt1_Evt = 21
-gt2_Evt = 22
-gt3_Evt = 23
-gt4_Evt = 24
-Ipo_Evt = 17
-New_Ipo_Evt=700
-
-###---------------------------------------------------------------------------
-# menus
-noisetypemenu = "Noise type: %t|multiFractal %x0|ridgedMFractal %x1|hybridMFractal %x2|heteroTerrain %x3|fBm %x4|turbulence %x5|Voronoi turb. %x6|vlNoise turb. %x7|noise %x8|cellNoise %x9|Marble %x10|lava_multiFractal %x11|slopey_noise %x12|duo_multiFractal %x13|distorted_heteroTerrain %x14|slickRock %x15|terra_turbulence %x16|rocky_fBm %x17|StatsByAlt_Terrain %x18|Double_Terrain %x19|Shattered_hTerrain %x20|vlhTerrain %x21"
-noisebasismenu = "Basis %t|Blender Original%x0|Original Perlin%x1|Improved Perlin%x2|Voronoi_F1%x3|Voronoi_F2%x4|Voronoi_F3%x5|Voronoi_F4%x6|Voronoi_F2-F1%x7|Voronoi Crackle%x8|CellNoise%x9"
-voronitypemenu = "Voronoi type %t|Distance %x0|Distance Squared %x1|Manhattan %x2|Chebychev %x3|Minkovsky 1/2 %x4|Minkovsky 4 %x5|Minkovsky %x6"
-tBasismodemenu = "Terrain basis mode: %t|noise %x0|ridged noise %x1|vlNoise %x2|ridged vlNoise %x3"
-effecttypemenu = ['Effect Type %t','No Effect %x0','Image %x1','Turbulence %x2','vlNoise %x3','Marble %x4', 'multiFractal %x5','ridgedMFractal %x6','hybridMFractal %x7','heteroTerrain %x8','fBm %x9', 'Gradient %x10','Waves and Bumps %x11','ZigZag %x12','Wavy %x13','Sine Bump %x14','Dots %x15','Rings / Dome %x16','Spiral %x17','Square / Piramide %x18','Blocks %x19','Grid %x20','Tech %x21','Crackle %x22','Sparse Cracks %x23','Shattered Rocks %x24','Lunar %x25','Cosine noise %x26','Spike noise %x27','Stone noise %x28','Flat Turb %x29','Flat Voroni %x30','Random noise %x31','Constant %x32','Custom Effect %x33' ]
-mixtypemenu = ['Mix Type %t','Effect only %x0','%l','Mix %x1','Add %x2','Subtract %x3','Multiply %x4','Difference %x5','Screen %x6','addmodulo %x7','Minimum %x8','Maximum %x9','%l','Warp Effect %x10','Warp Noise %x11']
-biastypemenu = "Bias %t|Sin bias %x0|Cos bias %x1|Tri bias %x2|Saw bias %x3|Default (no bias)%x4"
-sharptypemenu = "Sharpen %t|Soft %x0|Sharp %x1|Sharper %x2"
-filtermodemenu = "Filter Mode %t|No Filter %x0| %l|Default Filters %x1|IPOCurve Filter %x2|Custom Filter %x3"
-filtertypemenu = "Filter Type %t|Default Terrace %x0|Sharper Terrace %x1|Rounded Terrace %x2|Posterise Mixed %x3|Posterise %x4|Layered Peaks %x5|Peaked %x6|Smooth-thing %x7|Sin bias %x8|Cos bias %x9|Tri bias %x10|Saw bias %x11|Clamp Max. %x12"
-falloftypemenu = "Edge Falloff %t|No Edge Falloff %x0| %l|Soft Falloff %x1|Default Falloff %x2|Hard Falloff %x3|Linear Falloff Y %x4|Linear Falloff X %x5|Diagonal Falloff + %x6|Diagonal Falloff - %x7|Square %x8|Round %x9"
-randomtypemenu = "Random type: %t|setRandomSeed() : Blender.Noise %x0|Rand() : Blender.Mathutils %x1|genrand() : BPyMathutils MersenneTwister %x2"
-
-##--------------------------------------------------
-def Set_ReSet_Values():
- global fileinfo, filemessage
- global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly, WorldSpaceCo
- global NType, Basis, musgr, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, tBasismod, musgrTwo
- global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
- global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, AutoUpd, PreView, DefaultIpoName
-
- filemessage = ''
- fileinfo = ''
- effect_image = 'Load and Select image.'
- AutoUpd = Create( 0 )
- PreView = [ Create( 0 ), Create( 1.0 ), Create( 0.0 ) ]
- ## Coords controls:
- WorldSpaceCo = Create(0)
- iScale = [ Create( 1.0 ), Create( 1.0 ), Create( 0.25) ]
- Offset = [ Create( 0.0 ), Create( 0.0), Create( 0.0) ]
- Invert = [ Create( 0 ), Create( 0 ), Create( 0 ) ]
- NSize = [ Create( 1.0 ), Create( 2.0 ) ]
- Sx = [ Create( 1.0 ), Create( 1.0 ) ]
- Sy = [ Create( 1.0 ), Create( 1.0 ) ]
- Lx = [ Create( 0.0 ), Create( 0.0 ) ]
- Ly = [ Create( 0.0 ), Create( 0.0 ) ]
- ## Noise controls:
- NType = Create( 3 )
- Basis = [ Create( 0 ), Create( 0 ) ]
- musgr = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ), Create( 0.5 ) ]
- vlnoi = [ Create( 1.0 ), Create( 0 ) ]
- vlnoiTwo = [ Create( 1.0 ), Create( 0 ) ]
- voron = [ Create( 0 ), Create( 2.5 ) ]
- turbOne = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ]
- marbleOne = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ]
- tBasismod = Create(0)
- ## Effect controls:
- musgrTwo = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ) ]
- turbTwo = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ]
- marbleTwo = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ]
- Effect_Ctrl = [ Create( 0 ),Create( 2 ),Create( 0.0 ),Create( 0 ),Create( 0.0 ) ,Create( 0 ),Create( 2.0 ),Create( 0.5 ),Create( 0.5 ) ]
- CustomFX = [ Create('sin(x*pi)'), Create('cos(y*pi)'), Create('abs(a*b)*0.5') ]
- ## Filter controls:
- Min = Create( 0.0 )
- Max = Create( 1.0 )
- Falloff = [ Create( 2 ), Create( 1.0 ), Create( 1.0 ), Create( 0 ) , Create( 0 ) ]
- Filter_Mode = Create( 0 )
- Def_Filter_Ctrl = [ Create( 0 ), Create( 3.0 ) ]
- Ipo_Filter_Ctrl = [ Create( DefaultIpoName ), Create( 0 ), Create( 100.0 ), Create( 100.0 ) ]
- Filter_Order = Create( 0 )
- CustomFilt = [ Create('sqrt(h*h)**2'), Create('0'), Create('a') ]
- ## Randomise noise buttons:
- RandMod = Create( 1 )
- RSeed = Create( 0 )
- rand_I = Create( 0 )
- rand_H = Create( 0 )
- rand_S = Create( 0 )
- rand_L = Create( 1 )
-
-##-------------------------
-Set_ReSet_Values()
-
-
-####----------------------------------------------------------------------------------------------------
-###----------------------------------------------------------------------------------------------------
-## G.U.I.: text,backpanel,panel
-#--------------------------------------------------
-def draw_Text( ( x, y ), text, color, size ):
- glColor3f( color[0],color[1],color[2] )
- glRasterPos2d(x,y)
- txtsize = 'small', 'normal', 'large'
- Text( text, txtsize[ size ] )
-def draw_BackPanel( text, x, y, w, h, colors ):
- glColor3f( colors[0]*0.76, colors[1]*0.76, colors[2]*0.76 )
- glRecti( x, h, w, h+20 )
- glColor3f( colors[0], colors[1], colors[2] )
- glRecti( x, y, w, h )
- glColor3f( colors[0], colors[1], colors[2] )
- glRasterPos2d( x+10, h+5 )
- Text( text, 'small' )
-def draw_Panel( x, y, w, h, colors ):
- glColor3f( colors[0], colors[1], colors[2] )
- glRecti( x,y, w,h )
-def draw_Frame( text, x, y, w, h, color ):
- glColor3f( color[0], color[1], color[2] )
- glRasterPos2i(x+3,h-3)
- Text(text ,'small')
- stringwidth = GetStringWidth( text,'small' )
- glColor3f( color[0], color[1], color[2] )
- glBegin(Blender.BGL.GL_LINE_STRIP)
- glVertex2i(x,h)
- glVertex2i(x,y)
- glVertex2i(w,y)
- glVertex2i(w,h)
- glVertex2i(x+stringwidth+10,h)
- glEnd()
-def draw_Led( x, y, colors ):
- glColor3f( colors[0], colors[1], colors[2] )
- glRecti( x,y, x+4,y+4 )
-
-
-###----------------------------------------------------------------------------------------------------
-## G.U.I. Buttons:
-#----------------------------------------------------------------------------------------------------
-
-###-------------------------
-## Main / Mesh Buttons:
-#
-def MeshButtons( col, row, width, height ):
- global actme, actob, AutoUpd, txtFile, filemessage, fileinfo
-
- PushButton("I", UseMe_Evt, col[8], row[3], width[0], height[1], "Info: Here you can write some text to save with the file." )
- draw_Text( ( col[0], row[1]+5 ), 'Info: ' + fileinfo, black, 0 )
- txtFile = String("", No_Evt, col[0], row[2], width[9], height[1], txtFile.val, 256, "File: Full path and filename" )
- PushButton( "Select", SelFile_Evt, col[1], row[3], width[0], height[1], "File: Open FileBrowser and select *.ant file" )
- PushButton( "Load", LoadFile_Evt,col[2], row[3], width[2], height[1], "File: Load settings from file ( HotKey: L )" )
- PushButton( "Save", SaveFile_Evt,col[5], row[3], width[2], height[1], "File: Save settings to file ( HotKey: S )" )
-
- activeobname = ''
- if actme !=[]:
- activeobname = actob[0].name
- draw_Text( ( col[5]+5, row[7]-5 ), 'OB: ' + activeobname, [0.0,0.0,1.0], 1 )
- PushButton( "Add New Grid", New_Evt, col[0], row[6], width[4], height[2] )
- PushButton( "Assign Selected", App_Evt, col[5], row[6], width[4], height[2], 'Assign selected terrain')
-
-###-------------------------
-## Noise Buttons:
-#
-def NoiseButtons( col, row, width, height ):
- global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy, WorldSpaceCo
- global Ha, La, Oc, Of, Ga, Basis, NType, musgr, vlnoi, voron, turbOne, tBasismod
- global Depth, Hard, Amp, Freq, vlBasis, Distort, VFunc, VExp, VDep, marbleOne
- global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I
-
- bth = height[1]/2+5
- iScale[0] = Number("iScale:", Btn_Evt, col[5], row[2]+bth, width[3], height[1], iScale[0].val, -10.0, 10.0 , "Noise: Intensity Scale." )
- Invert[0] = Toggle("Inv.", Btn_Evt, col[9], row[2]+bth, width[0], height[1], Invert[0].val, "Noise: Invert")
- Offset[0] = Number("Offset:", Btn_Evt, col[5], row[3]+bth, width[4], height[1], Offset[0].val, -10.0, 10.0 , "Noise: Offset " )
- NSize[0] = Number("Noise Size:",Btn_Evt, col[5], row[5], width[4], height[2], NSize[0].val, 0.001, 10.0 , "Noise Size" )
- Sx[0] = Number("Size X:", Btn_Evt, col[5], row[6], width[4], height[1], Sx[0].val, 0.001, 10.0 , "Size X" )
- Sy[0] = Number("Size Y:", Btn_Evt, col[5], row[7], width[4], height[1], Sy[0].val, 0.001, 10.0 , "Size Y" )
- Lx[0] = Number("Loc X:", Btn_Evt, col[5], row[8], width[4], height[1], Lx[0].val, -10000.0, 10000.0 , "Loc X" )
- Ly[0] = Number("Loc Y:", Btn_Evt, col[5], row[9],width[4], height[1], Ly[0].val, -10000.0, 10000.0 , "Loc Y" )
- WorldSpaceCo = Menu( "Coordinates %t|Local Space %x0|World Space %x1|Center at CursorPos %x2", Btn_Evt, col[5], row[10], width[4], height[1], WorldSpaceCo.val, "x,y,z coordinates for noise, effect and height falloff " )
-
- NType = Menu( noisetypemenu, Btn_Evt, col[0], row[2], width[4], height[2], NType.val, "Noise type" )
- if NType.val == 6:
- voron[0] = Menu( voronitypemenu, Btn_Evt, col[0], row[3], width[4], height[1], voron[0].val, "Voronoi type" )
- else:
- if NType.val != 9:
- Basis[0] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[0].val, "Noise Basis" )
-
- if NType.val in [0,1,2,3,4,11,12,13,14,15,17,18,19,20,21]:
- musgr[0] = Slider( "H: ", Btn_Evt, col[0], row[5], width[4], height[1], musgr[0].val, 0.0, 3.0, 0 , "H" )
- musgr[1] = Slider( "Lacu: ", Btn_Evt, col[0], row[6], width[4], height[1], musgr[1].val, 0.0, 6.0, 0 , "Lacunarity" )
- musgr[2] = Slider( "Octs: ", Btn_Evt, col[0], row[4], width[4], height[1], musgr[2].val, 0, 12, 0 , "Octaves" )
- if NType.val in [1,2,3,13,14,15,18,19,20,21]:
- musgr[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgr[3].val, 0.0, 6.0, 0 , "Offset" )
- if NType.val in [1,2,13,15,18]:
- musgr[4] = Slider( "Gain: ", Btn_Evt, col[0], row[8], width[4], height[1], musgr[4].val, 0.0, 6.0, 0 , "Gain" )
- if NType.val == 19:
- musgr[5] = Slider( "Thresh: ", Btn_Evt, col[0], row[8], width[4], height[1], musgr[5].val, 0.001, 2.0, 0 , "Threshold" )
- if NType.val in [5,6,7,16]:
- turbOne[0] = Number( "Depth:", Btn_Evt, col[0], row[4], width[4], height[1], turbOne[0].val, 0, 12, "Octaves")
- turbOne[1] = Toggle( "Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbOne[1].val, "Soft noise / Hard noise")
- turbOne[2] = Slider( "Amp:", Btn_Evt, col[0], row[6], width[4], height[1], turbOne[2].val, 0.0, 3.0, 0, "Ampscale ")
- turbOne[3] = Slider( "Freq:", Btn_Evt, col[0], row[7], width[4], height[1], turbOne[3].val, 0.0, 6.0, 0, "Freqscale")
- if NType.val in [18,19]:
- tBasismod = Menu( tBasismodemenu, Btn_Evt, col[0], row[9], width[4], height[1], tBasismod.val, "Terrain basis mode.")
- if NType.val == 6:
- if voron[0].val == 6:
- voron[1] = Slider( "Exp: ", Btn_Evt, col[0], row[8], width[4], height[1], voron[1].val, 0.0,10.0, 0, "Minkovsky exponent")
- if NType.val in [7,11,12,14,20,21]:
- vlnoi[0] = Slider( "Dist: ", Btn_Evt, col[0], row[8], width[4], height[1], vlnoi[0].val, 0.0, 10.0, 0 , "Distort" )
- if NType.val in [7,13,14,15,21]:
- vlnoi[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[9], width[4], height[1], vlnoi[1].val, "Distortion Noise")
- if NType.val == 10:
- marbleOne[0] = Number( "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleOne[0].val, 0, 12, "Octaves")
- marbleOne[2] = Slider( "Turb: ", Btn_Evt, col[0], row[7], width[4], height[1], marbleOne[2].val, 0.0,20.0, 0, "Turbulence ")
- marbleOne[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleOne[3].val, "Bias")
- marbleOne[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleOne[5].val, 0.0,20.0, 0, "ReScale")
- if marbleOne[3].val != 4:
- marbleOne[4] = Menu(sharptypemenu, Btn_Evt ,col[0], row[5], width[4], height[1], marbleOne[4].val, "Sharpen")
-
- RandMod = Menu( randomtypemenu, No_Evt, col[0], row[10], width[0], height[1], RandMod.val, "Random Type" )
- rand_H = Toggle("TH",No_Evt ,col[1], row[10], width[0], height[1], rand_H.val, "Randomise Terrain Height ( in Height panel )")
- rand_I = Toggle("NH",No_Evt ,col[2], row[10], width[0], height[1], rand_I.val, "Randomise Noise Height")
- rand_S = Toggle("NS",No_Evt ,col[3], row[10], width[0], height[1], rand_S.val, "Randomise Noise Size")
- rand_L = Toggle("NL",No_Evt ,col[4], row[10], width[0], height[1], rand_L.val, "Randomise Noise Location")
-
-###-------------------------
-## Effect Buttons:
-#
-def EffectButtons( col, row, width, height ):
- global Effect_Type, Effect_Ctrl, Blend_Effect, CustomFX
- global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy
- global BasisTwo, turbTwo, marbleTwo, vlnoiTwo, musgrTwo
-
- Effect_Ctrl[0] = Menu( '|'.join( effecttypemenu ), Btn_Evt, col[0], row[2], width[4], height[2], Effect_Ctrl[0].val, "Effect: Type" )
- if Effect_Ctrl[0].val != 0:
- Effect_Ctrl[1] = Menu( '|'.join( mixtypemenu ), Btn_Evt, col[5], row[2], width[4], height[2], Effect_Ctrl[1].val, "Mix: Type" )
- if Effect_Ctrl[1].val in [10,11]:
- Effect_Ctrl[2] = Slider("Warp: ", Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" )
- else: Effect_Ctrl[2] = Slider("Mix: ",Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" )
-
- iScale[1] = Number("iScale:", Btn_Evt, col[5], row[4], width[3], height[1], iScale[1].val, -20.0, 20.0 , "Effect: Intensity Scale " )
- Invert[1] = Toggle("Inv.", Btn_Evt, col[9], row[4], width[0], height[1], Invert[1].val, "Effect: Invert")
- Offset[1] = Number("Offset:", Btn_Evt, col[5], row[5], width[4], height[1], Offset[1].val, -20.0, 20.0 , "Effect: Offset " )
- NSize[1] = Number("Frequency:",Btn_Evt, col[5], row[6], width[4], height[1], NSize[1].val, 0.001, 100.0, "Effect Frequency ( Scale )" )
- Sx[1] = Number("Freq X:", Btn_Evt, col[5], row[7], width[4], height[1], Sx[1].val, -50.0, 50.0 , "Effect Frequency X ( ScaleX )" )
- Sy[1] = Number("Freq Y:", Btn_Evt, col[5], row[8], width[4], height[1], Sy[1].val, -50.0, 50.0 , "Effect Frequency Y ( ScaleY )" )
- Lx[1] = Number("Loc X:", Btn_Evt, col[5], row[9], width[4], height[1], Lx[1].val, -1000.0, 1000.0 , "Effect Loc X" )
- Ly[1] = Number("Loc Y:", Btn_Evt, col[5], row[10], width[4], height[1], Ly[1].val, -1000.0, 1000.0 , "Effect Loc Y" )
-
- if Effect_Ctrl[0].val == 1:
- PushButton("Load Image", Load_Evt, col[0], row[4], width[4], height[2] , "Load Image")
- PushButton("Select Image", Sel_Evt, col[0], row[6], width[4], height[3] , "Select Image")
- draw_Text( ( col[0]+5, row[7] ), effect_image, black, 1 )
-
- if Effect_Ctrl[0].val in [2,3,4,5,6,7,8,9]:
- Basis[1] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[1].val, "Basis" )
-
- if Effect_Ctrl[0].val == 2:
- turbTwo[0] = Number( "Depth:", Btn_Evt, col[0], row[4], width[4], height[1], turbTwo[0].val, 1, 12, "Octaves")
- turbTwo[1] = Toggle("Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbTwo[1].val, "Hard noise")
- turbTwo[2] = Slider( "Amp:", Btn_Evt, col[0], row[6], width[4], height[1], turbTwo[2].val, 0.0, 3.0, 0, "Ampscale ")
- turbTwo[3] = Slider( "Freq:", Btn_Evt, col[0], row[7], width[4], height[1], turbTwo[3].val, 0.0, 6.0, 0, "Freqscale")
- if Effect_Ctrl[0].val == 3:
- vlnoiTwo[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[4], width[4], height[1], vlnoiTwo[1].val, "Distortion Noise")
- vlnoiTwo[0] = Slider( "Dist: ", Btn_Evt, col[0], row[5], width[4], height[1], vlnoiTwo[0].val, 0.0, 10.0, 0 , "Distort" )
- if Effect_Ctrl[0].val == 4:
- marbleTwo[0] = Number( "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleTwo[0].val, 1, 12, "Octaves")
- marbleTwo[2] = Slider( "Turb: ", Btn_Evt, col[0], row[7], width[4], height[1], marbleTwo[2].val, 0.0,20.0, 0, "Turbulence")
- marbleTwo[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleTwo[3].val, "Bias")
- marbleTwo[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleTwo[5].val, 0.0,20.0, 0, "ReScale")
- if marbleTwo[3].val != 4:
- marbleTwo[4] = Menu(sharptypemenu,Btn_Evt ,col[0], row[5], width[4], height[1], marbleTwo[4].val, "Sharpen")
-
- if Effect_Ctrl[0].val in [5,6,7,8,9]:
- musgrTwo[0] = Slider( "H: ", Btn_Evt, col[0], row[5], width[4], height[1], musgrTwo[0].val, 0.0, 3.0, 0 , "H" )
- musgrTwo[1] = Slider( "Lacu: ", Btn_Evt, col[0], row[6], width[4], height[1], musgrTwo[1].val, 0.0, 6.0, 0 , "Lacunarity" )
- musgrTwo[2] = Slider( "Octs: ", Btn_Evt, col[0], row[4], width[4], height[1], musgrTwo[2].val, 0, 12, 0 , "Octaves" )
- if Effect_Ctrl[0].val in [6,7,8]:
- musgrTwo[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgrTwo[3].val, 0.0, 6.0, 0 , "Offset" )
- if Effect_Ctrl[0].val in [6,7]:
- musgrTwo[4] = Slider( "Gain: ", Btn_Evt, col[0], row[8], width[4], height[1], musgrTwo[4].val, 0.0, 6.0, 0 , "Gain" )
-
- if Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31:
- Effect_Ctrl[5] = Number("Depth:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[5].val, 0, 12 , "Fractalize Effect: Octaves" )
- Effect_Ctrl[4] = Number("Distort:",Btn_Evt, col[0], row[7], width[4], height[1], Effect_Ctrl[4].val, 0.0, 50.0 , "Distort Effect: Amount" )
- Effect_Ctrl[6] = Slider("Freq:", Btn_Evt, col[0], row[5], width[4], height[1], Effect_Ctrl[6].val, 0.0, 6.0, 0, "Fractalize Effect: Frequency" )
- Effect_Ctrl[7] = Slider("Amp:", Btn_Evt, col[0], row[6], width[4], height[1], Effect_Ctrl[7].val, 0.0, 3.0, 0, "Fractalize Effect: Amplitude" )
- if Effect_Ctrl[0].val < 22:
- Effect_Ctrl[3] = Menu(biastypemenu, Btn_Evt ,col[0], row[3], width[4], height[1], Effect_Ctrl[3].val, "Effect bias")
- if Effect_Ctrl[0].val in [31,32]:
- Effect_Ctrl[8] = Number("Amount:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[8].val, -20.0, 20.0, "Effect: Amount" )
- if Effect_Ctrl[0].val == 33:
- draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 )
- CustomFX[0] = String( "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFX[0].val,96, "a" )
- CustomFX[1] = String( "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFX[1].val,96, "b" )
- CustomFX[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFX[2].val,96, "result" )
-
-###-------------------------
-## Filter / Height Buttons:
-#
-def FilterButtons( col, row, width, height ):
- global iScale, Offset, Invert, Min, Max, Falloff, CustomFilt
- global Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, DefaultIpoName, Filter_Order
-
- iScale[2] = Number("Height:", Btn_Evt, col[5], row[2], width[3], height[2], iScale[2].val, -10.0, 10.0 , "Terrain Height: Scale" )
- Invert[2] = Toggle("Inv.", Btn_Evt, col[9], row[2], width[0], height[2], Invert[2].val, "Terrain Height: Invert")
- Offset[2] = Number("Offset:", Btn_Evt, col[5], row[3], width[4], height[1], Offset[2].val, -10.0, 10.0 , "Terrain Height: Offset" )
- Max = Number( "Plateau:", Btn_Evt, col[5], row[5], width[4], height[1], Max.val, Min.val, 1.0 , "Terrain Height: Clamp Max. ( Plateau )" )
- Min = Number( "Sealevel:", Btn_Evt, col[5], row[6], width[4], height[1], Min.val, -1.0, Max.val , "Terrain Height: Clamp Min. ( Sealevel )" )
- Falloff[0] = Menu( falloftypemenu, Btn_Evt ,col[5], row[9], width[4], height[2], Falloff[0].val, "Terrain Height: Edge falloff")
- if Falloff[0].val !=0:
- Falloff[1] = Number("X:", Btn_Evt, col[5], row[10], width[1], height[1], Falloff[1].val , 0.01, 100.0 , "Edge falloff: X Size" )
- Falloff[2] = Number("Y:", Btn_Evt, col[8], row[10], width[1], height[1], Falloff[2].val , 0.01, 100.0 , "Edge falloff: Y Size" )
- Falloff[4] = Toggle("Inv.", Btn_Evt, col[7], row[10], width[0], height[1], Falloff[4].val, "Edge falloff: Invert")
- Falloff[3] = Toggle("Edge At Sealevel", Btn_Evt, col[5], row[7], width[4], height[1], Falloff[3].val, "Edge falloff: Edge at Sealevel")
-
- Filter_Mode = Menu( filtermodemenu, No_Evt, col[0], row[2], width[4], height[2], Filter_Mode.val, "Filter: Mode")
- if Filter_Mode.val ==1:
- Def_Filter_Ctrl[0] = Menu( filtertypemenu, Btn_Evt, col[0], row[5], width[4], height[2], Def_Filter_Ctrl[0].val, "Filter: Type")
- Def_Filter_Ctrl[1] = Number("Amount: ", Btn_Evt, col[0], row[6], width[4], height[1], Def_Filter_Ctrl[1].val, 0.1, 100.0 , "Filter: Amount" )
-
- if Filter_Mode.val ==2:
- Ipo_Filter_Ctrl[0] = String("IP:", Ipo_Evt, col[0], row[5], width[4], height[2], Ipo_Filter_Ctrl[0].val,20, "Ipo datablock name" )
- if Ipo_Filter_Ctrl[0].val !='':
- Ipo_Filter_Ctrl[1] = Number("Use This Curve:",Ipo_Evt, col[0], row[7], width[4], height[3], Ipo_Filter_Ctrl[1].val, 0, 29, "Select curve to use" )
- Ipo_Filter_Ctrl[2] = Number("Curve Length:", Ipo_Evt, col[0], row[8], width[4], height[1], Ipo_Filter_Ctrl[2].val, 0.0, 1000.0, "X: Length (number of frames) of the selected curve." )
- Ipo_Filter_Ctrl[3] = Number("Curve Height:", Ipo_Evt, col[0], row[9], width[4], height[1], Ipo_Filter_Ctrl[3].val, 0.0, 1000.0, "Y: Height (offset) of the selected curve." )
- else:
- draw_Text( ( col[0]+5, row[6] ), 'Enter Ipo DataBlock name,' , black, 0 )
- draw_Text( ( col[0]+5, row[9] ), 'or else:' , black, 0 )
- PushButton( "New IpoDataBlock/Object", New_Ipo_Evt, col[0], row[10], width[4], height[1], "Creates new Ipo Object(Empty), and Ipo DataBlock(curves)' to use as height filter")
-
- if Filter_Mode.val ==3:
- draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 )
- CustomFilt[0] = String( "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFilt[0].val,96, "a" )
- CustomFilt[1] = String( "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFilt[1].val,96, "b" )
- CustomFilt[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFilt[2].val,96, "result" )
- if Filter_Mode.val !=0:
- Filter_Order = Toggle("Change Filter Order", Btn_Evt, col[0], row[3], width[4], height[1], Filter_Order.val, "Filter Order: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff.")
-
-###-------------------------
-## Option / Generate Image Buttons:
-#
-def OptionButtons( col, row, width, height ):
- global PreView, previewname
-
- PreView[0] = Toggle("Make Image", No_Evt, col[0], row[2], width[4], height[2], PreView[0].val, "Image: On/Off (Make a new Image in UV/ImageEditor Window, and give a name to it)")
- if PreView[0].val !=0:
- previewname = String( "IM:", No_Evt, col[0], row[3], width[4], height[1] ,previewname.val, 16, "IM:Name, Render terrain height to this image" )
- PreView[1] = Number("", Im_Evt, col[0], row[4], width[1], height[1], PreView[1].val, 0.0, 10.0, "Image: Intensity Scale")
- PreView[2] = Number("", Im_Evt, col[3], row[4], width[1], height[1], PreView[2].val,-10.0, 10.0, "Image: Offset")
- PushButton( "Draw Image", Im_Evt, col[0], row[5], width[4], height[1] , "Image: Update image ( KEY: V )")
- draw_Text( ( col[5], row[1] ), 'Create yourself a new image', black, 0 )
- draw_Text( ( col[5], row[2] ), 'in UV/Image Editor Window,', black, 0 )
- draw_Text( ( col[5], row[3] ), 'give it a name,', black, 0 )
- draw_Text( ( col[5], row[4] ), 'and save it manualy.', black, 0 )
-
-####--------------------------------------------------------------------------
-###--------------------------------------------------------------------------
-## Draw G.U.I. -------------------------------------------------------------
-#--------------------------------------------------------------------------
-def drawgui():
- global guitabs, ledcolor, FullScreen, AutoUpd, RandMod, RSeed, filemessage
- global Effect_Ctrl, Filter_Mode, Falloff, PreView, rand_H, rand_S, rand_L, rand_I
-
- glClearColor(background[0],background[1],background[2],background[3])
- glClear(GL_COLOR_BUFFER_BIT)
- scissorbox=Buffer(GL_FLOAT,4)
- glGetFloatv(GL_SCISSOR_BOX,scissorbox)
- scissbleft=int(scissorbox[0])
- scissbbase=int(scissorbox[1])
- scissbwidth=int(scissorbox[2])
- scissbheight=int(scissorbox[3])
- xstart = 5
- ystart = 5
- xgap = 5
- ygap = 5
- if FullScreen.val==1:
- guiwidth = scissbwidth-10
- guiheight = scissbheight-25
- if guiwidth < size_x/2:
- guiwidth = size_x/2
- if guiheight < size_y/2:
- guiheight = size_y/2
- else:
- guiwidth = size_x
- guiheight = size_y
- col,row = [],[]
- xpart = ( ( guiwidth-xstart ) / columns )
- ypart = ( ( guiheight-ystart ) / rows )
- width = []
- for c in xrange( columns ):
- col.append( xgap + xpart * c + xstart )
- width.append( xpart*(c+1)-xgap )
- height = [ (ypart-ygap)/2 , ypart-ygap, (ypart*3-ygap)/2, ypart*2-ygap, (ypart*5-ygap)/2 ]
- for r in xrange( rows ):
- row.append( ygap + ypart * r + ystart )
- row.reverse()
-
- ###-------------------------
- ## Draw G.U.I.:
- draw_BackPanel( 'Another Noise Tool 1.05', xstart, ystart, guiwidth, guiheight + ygap, lightgrey )
-
- FullScreen = Toggle("", Scrn_Evt, guiwidth-32, guiheight+ygap+3, 15, 15, FullScreen.val ,"FullScreen" )
- PushButton( "X", End_Evt, guiwidth-16, guiheight+ygap+3, 15, 15, "Exit" )
- draw_Text(( guiwidth-(guiwidth/2)-width[0], guiheight+ygap+5 ), filemessage, white, 0 )
-
- # gui tabs
- guitabs[0] = Toggle("Main", gt0_Evt, col[0], row[0], width[1], height[1], guitabs[0].val ,"Main / Mesh settings" )
- guitabs[1] = Toggle("Noise", gt1_Evt, col[2], row[0], width[1], height[1], guitabs[1].val ,"Noise settings" )
- guitabs[2] = Toggle("Effect", gt2_Evt, col[4], row[0], width[1], height[1], guitabs[2].val ,"Add Effect" )
- guitabs[3] = Toggle("Height", gt3_Evt, col[6], row[0], width[1], height[1], guitabs[3].val ,"Height Filter" )
- guitabs[4] = Toggle("Options", gt4_Evt, col[8], row[0], width[1], height[1], guitabs[4].val ,"Options" )
-
- if guitabs[0].val !=0: MeshButtons( col, row, width, height )
- elif guitabs[1].val !=0: NoiseButtons( col, row, width, height )
- elif guitabs[2].val !=0: EffectButtons( col, row, width, height )
- elif guitabs[3].val !=0: FilterButtons( col, row, width, height )
- elif guitabs[4].val !=0: OptionButtons( col, row, width, height )
- else: # some info
- draw_Panel( col[0], row[0]-5, col[9]+width[0], row[10]-10, black )
- draw_Text( ( col[0]+5, row[1] ), 'Another Noise Tool v.1.05', ledcolors[0], 2 )
- draw_Text( ( col[0]+5, row[2] ), 'by: Jimmy Hazevoet, 01/2005-03/2007', ledcolors[1], 2 )
- draw_Text( ( col[0]+5, row[3] ), 'v.1.05: build/tested in: Blender 2.43 (Wndws)', ledcolors[2], 1 )
- draw_Text( ( col[0]+5, row[4] ), 'HotKeys: ----------------------------', ledcolors[3], 2 )
- draw_Text( ( col[0]+5, row[5] ), 'Space = Update mesh', ledcolors[4], 2 )
- draw_Text( ( col[0]+5, row[6] ), 'V = Update Image', ledcolors[5], 2 )
- draw_Text( ( col[0]+5, row[7] ), 'R = Randomise', ledcolors[6], 2 )
- draw_Text( ( col[0]+5, row[8] ), 'L = Load from file', ledcolors[7], 2 )
- draw_Text( ( col[0]+5, row[9] ), 'S = Save to file', ledcolors[8], 2 )
- draw_Text( ( col[0]+5, row[10] ),'Q = Quit', ledcolors[9], 2 )
-
- # auto/generate/randomise buttons
- rand_on_off = 0
- if rand_H.val !=0: rand_on_off = 1
- elif rand_I.val !=0: rand_on_off = 1
- elif rand_S.val !=0: rand_on_off = 1
- elif rand_L.val !=0: rand_on_off = 1
- else: rand_on_off = 0
- if rand_on_off != 0:
- if RandMod.val in [1,2]:
- PushButton( "Randomise", Rndm_Evt, col[2], row[12], width[2], height[2] , "Randomise Noise ( KEY: R )")
- else: RSeed = Number("Seed: ", Rndm_Evt, col[2], row[12], width[2], height[2], RSeed.val, 0, 255 , "Random Seed: If seed = 0, the current time will be used as seed." )
- AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" )
- PushButton("Update", Upd_Evt, col[5], row[12], width[4], height[2] , "Generate / Update. ( KEY: SPACE )")
- else:
- AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" )
- PushButton("Update", Upd_Evt, col[2], row[12], width[7], height[2] , "Generate / Update. ( KEY: SPACE )")
- ####---------------------------------------------------------------------------
-
-###---------------------------------------------------------------------------
-##---------------------------------------------------------------------------
-# Key Events:
-
-def events(evt, val):
- global PreView, txtFile, AutoUpd, PreView
-
- ## hotkey: Q = Quit
- if (evt == QKEY and not val):
- name = "Quit ?%t|No %x0|Yes %x1"
- result = Blender.Draw.PupMenu(name)
- if result==1:
- Exit()
-
- ## hotkey: Space = Generate/Update terrain
- if (evt == SPACEKEY and not val):
- do_it()
-
- ## hotkey: R = Randomise noise
- if (evt in [ RKEY ] and not val):
- if AutoUpd.val != 0:
- do_it_random()
- else:
- randomiseNoise()
- Draw()
-
- ## hotkey: V = Update image
- if PreView[0].val != 0:
- if (evt in [ VKEY, RKEY ] and not val):
- do_it_preview()
-
- ## hotkey: L = Load from file
- if (evt == LKEY and not val):
- loadmenu = "Load file ?%t|" + txtFile.val
- loadresult = Blender.Draw.PupMenu(loadmenu)
- if loadresult==1:
- LoadPreset(txtFile.val)
- if AutoUpd.val != 0:
- do_it()
- else: Draw()
-
- ## hotkey: S = Save to file
- if (evt == SKEY and not val):
- savemenu = "Save file ?%t|" + txtFile.val
- saveresult = Blender.Draw.PupMenu(savemenu)
- if saveresult==1:
- SavePreset(txtFile.val)
- Draw()
-
-###---------------------------------------------------------------------------
-##---------------------------------------------------------------------------
-# Button events:
-
-def bevents(evt):
- global txtFile, effect_image, PreView, fileinfo, filemessage
- global Filter_Mode, Ipo_Filter_Ctrl, iponame, thiscurve, selectedcurve
- global antfilename, terrainname
- global actob, actme
-
- # quit/reset event
- if (evt == End_Evt ):
- name = "OK ?%t|Reset %x1|Quit %x2"
- result = Blender.Draw.PupMenu(name)
- if result==1:
- Set_ReSet_Values()
- Draw()
- elif result==2:
- Exit()
-
- ## file info string event
- if (evt == UseMe_Evt ):
- result = Blender.Draw.PupStrInput("Info: ", fileinfo, 96)
- if result:
- fileinfo = result
- Draw()
- else: return
-
- ## none event
- if (evt in [No_Evt, Scrn_Evt] ):
- Draw()
-
- ## image event
- if (evt == Im_Evt ):
- do_it_preview()
-
- ## generate/update event
- if (evt == Upd_Evt ):
- if PreView[0].val != 0:
- do_it_preview()
- do_it()
-
- ## mesh button event
- if (evt == Msh_Evt):
- if AutoUpd.val != 0:
- do_it()
- else: Draw()
-
- ## button event
- if (evt == Btn_Evt ):
- if AutoUpd.val != 0:
- if PreView[0].val != 0:
- do_it_preview()
- do_it()
- else: Draw()
-
- ## randomise event
- if (evt == Rndm_Evt ):
- if AutoUpd.val != 0:
- do_it_random()
- else:
- randomiseNoise()
- if PreView[0].val != 0:
- do_it_preview()
- Draw()
-
- ###---------------------------------------------------------
- ## Effect Image Load/Select:
- if (evt == Load_Evt ):
- Blender.Window.FileSelector ( load_image, 'LOAD IMAGE')
- if (evt == Sel_Evt ):
- try: effect_image = Image_Menu()
- except: pass
- if AutoUpd.val != 0:
- do_it()
- else: Draw()
-
- ###---------------------------------------------------------
- ## Make New IPOCurve to use as Filter:
- if (evt == New_Ipo_Evt ):
- objname = Create("ANT_Ipo_Empty")
- iponame = Create("ANT_IPO")
- block = []
- block.append("Enter new names")
- block.append("and hit OK button")
- block.append(("OB: ", objname, 0, 30, "New Ipo Object Name. (Object type = 'Empty')"))
- block.append(("IP: ", iponame, 0, 30, "New Ipo DataBlock Name"))
- block.append("Open IpoCurveEditor")
- block.append("select Ipo DataBlock" )
- block.append("'Pin' the view" )
- block.append("and edit the curves." )
- retval = PupBlock("Make A.N.T. IpoCurve Object", block)
- if retval !=0:
- ANTAutoIpo( objname.val, iponame.val )
- Ipo_Filter_Ctrl[0].val = iponame.val
-
- ###---------------------------------------------------------
- ## get IPOCurve to use as Filter:
- if (evt in [Ipo_Evt, New_Ipo_Evt] ):
- if Filter_Mode.val == 2:
- if AutoUpd.val != 0:
- try:
- ipoblockname = Ipo.Get( Ipo_Filter_Ctrl[0].val )
- thiscurve = ipoblockname.getCurves()
- selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ]
- if PreView[0].val != 0:
- do_it_preview()
- #if AutoUpd.val != 0:
- do_it()
- except: pass
- else:
- try:
- ipoblockname = Ipo.Get( Ipo_Filter_Ctrl[0].val )
- thiscurve = ipoblockname.getCurves()
- selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ]
- if PreView[0].val != 0:
- do_it_preview()
- else:
- Draw()
- except: pass
-
- ###---------------------------------------------------------
- ## gui tabs
- if (evt == gt0_Evt ):
- if guitabs[0].val == 1:
- guitabs[1].val = ( 0 )
- guitabs[2].val = ( 0 )
- guitabs[3].val = ( 0 )
- guitabs[4].val = ( 0 )
- Draw()
- if (evt == gt1_Evt ):
- if guitabs[1].val == 1:
- guitabs[0].val = ( 0 )
- guitabs[2].val = ( 0 )
- guitabs[3].val = ( 0 )
- guitabs[4].val = ( 0 )
- Draw()
- if (evt == gt2_Evt ):
- if guitabs[2].val == 1:
- guitabs[0].val = ( 0 )
- guitabs[1].val = ( 0 )
- guitabs[3].val = ( 0 )
- guitabs[4].val = ( 0 )
- Draw()
- if (evt == gt3_Evt ):
- if guitabs[3].val == 1:
- guitabs[0].val = ( 0 )
- guitabs[1].val = ( 0 )
- guitabs[2].val = ( 0 )
- guitabs[4].val = ( 0 )
- Draw()
- if (evt == gt4_Evt ):
- if guitabs[4].val == 1:
- guitabs[0].val = ( 0 )
- guitabs[1].val = ( 0 )
- guitabs[2].val = ( 0 )
- guitabs[3].val = ( 0 )
- Draw()
-
- ###---------------------------------------------------------
- ## load and save all settings:
- if (evt == SelFile_Evt ):
- Blender.Window.FileSelector ( callback, "Select .ant File")
- if (evt == LoadFile_Evt ):
- loadmenu = "Load file ?%t|" + txtFile.val
- loadresult = Blender.Draw.PupMenu(loadmenu)
- if loadresult==1:
- LoadPreset(txtFile.val)
- Draw()
- if AutoUpd.val != 0:
- do_it()
- if (evt == SaveFile_Evt ):
- savemenu = "Save file ?%t|" + txtFile.val
- saveresult = Blender.Draw.PupMenu(savemenu)
- if saveresult==1:
- SavePreset(txtFile.val)
- Draw()
-
- ###---------------------------------------------------------
- # New Grid
- ###-------------------------
- if (evt == New_Evt):
- scn = Blender.Scene.GetCurrent()
- gridname = Create("Terrain")
- gridres = Create(256)
- curspos = Create(0)
- block = []
- block.append(("OB: ", gridname, 0, 30, "New Object Name."))
- block.append(("Resol: ", gridres, 4, 1024, "New grid resolution"))
- block.append(("At Cursor", curspos, "New grid at cursor position"))
- retval = PupBlock("New Grid Mesh", block)
- if retval !=0:
- MakeGridMesh( gridres.val, gridname.val, curspos.val, scn )
- obj = scn.objects.active
- if obj.type == 'Mesh':
- actob=[]
- actme=[]
- actob.append( obj )
- actme.append( actob[0].getData(mesh=1) )
- Blender.Redraw()
-
- ###---------------------------------------------------------
- # Assign Grid
- ###-------------------------
- if (evt == App_Evt):
- scn = Blender.Scene.GetCurrent()
- obj = scn.objects.active
- if obj:
- if obj.type == 'Mesh':
- actob=[]
- actme=[]
- actob.append( obj )
- actme.append( actob[0].getData(mesh=1) )
- Draw()
-
- ###-------------------------
- if (evt not in [LoadFile_Evt,SaveFile_Evt] ):
- filemessage = ''
- #Draw()
-
- ### end events. -------------------------
-
-####-------------------------------------------------------------------------------------
-###-------------------------------------------------------------------------------------
-##-------------------------------------------------------------------------------------
-#-------------------------------------------------------------------------------------
-
-##----------------------------------
-# A.N.T. Auto Ipo generator:
-def ANTAutoIpo( objname, iponame ):
- scn=Scene.GetCurrent()
- # Deselect all objects:
- scn.objects.selected=[]
- # Create new 'ANT_IPO_OBJECT':
- obj = scn.objects.new('Empty', objname )
- obj.setDrawMode(8)
- obj.select(1)
- obj.layers = Window.ViewLayers()
- # Set current frame at 1:
- frame = Get('curframe')
- if frame !=1:
- Set('curframe',1)
- frame = Get('curframe')
- # Insert IpoKeys:
- obj.setLocation(0.0, 0.0, 0.0)
- obj.insertIpoKey(0)
- Set('curframe',101)
- obj.setLocation(100.0, 100.0, 100.0)
- obj.insertIpoKey(0)
- Set('curframe',1)
- # Set Ipo name:
- ip = obj.getIpo()
- ip.name = iponame
- #-------------------------
- print "New ANT_IPO: " + objname +" (Object) and " + iponame + " (Ipo DataBlock) Created!"
- #-------------------------
-
-##-------------------------------------------------------------------------------------
-
-##-------------------------
-# Generate random numbers:
-def randnum(low,high):
- global RandMod, RSeed
- if RandMod.val == 0:
- # Noise.random setRandomSeed
- s = Noise.setRandomSeed( RSeed.val )
- num = Noise.random()
- num = num*(high-low)
- num = num+low
- elif RandMod.val == 1:
- # Mathutils.Rand
- num = Mathutils.Rand(low,high)
- else:
- # BPyMathutils Mersenne Twister genrand
- num = genrand()
- num = num*(high-low)
- num = num+low
- return num
-
-##-------------------------
-# Randomise noise: height, size and location:
-def randomiseNoise():
- global rand_I, rand_H, rand_S, rand_L, NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy
-
- if rand_I.val !=0:
- iScale[0] = Create( randnum( 0.2 , 3.0 ) )
- Offset[0] = Create( randnum(-1.0 , 1.0 ) )
- if rand_H.val !=0:
- iScale[2] = Create( randnum( 0.10 , 1.0 ) )
- Offset[2] = Create( randnum(-0.25 , 0.25 ) )
- if rand_S.val !=0:
- NSize[0] = Create( randnum( 0.25 , 2.5 ) )
- #Sx[0] = Create( randnum( 0.5 , 1.5 ) )
- #Sy[0] = Create( randnum( 0.5 , 1.5 ) )
- if rand_L.val !=0:
- Lx[0] = Create( randnum( -10000 , 10000 ) )
- Ly[0] = Create( randnum( -10000 , 10000 ) )
-
-##-------------------------------------------------------------------------------------
-
-###--------------------------
-# Load Image:
-def load_image( ImageFileName ):
- Image.Load( ImageFileName )
-
-###--------------------------
-# Select Image Menu:
-def Image_Menu():
- try:
- names=[]
- imagelist = Image.Get()
- imagelist.reverse()
- for numbers, obnames in enumerate( imagelist ):
- n = obnames.getName()
- names.append( n )
- imlistText = string.join( [ '|' + str(names[key]) + '%x' + str(key) for key in xrange(numbers+1) ], '' )
- image_menu = Blender.Draw.PupMenu( "Images: %t" + imlistText )
- if image_menu == -1:
- return ''
- return imagelist[ image_menu ].getName()
- except:
- return 'No image found!'
-
-###--------------------------
-# Get Image Pixels:
-def Image_Func( x,y ):
- try:
- pic = Image.Get( effect_image )
- except:
- return 0.0
- w, h = pic.getSize()
- x, y = x,-y
- x = int(w * ((x + 1.0) % 2.0) / 2.0)
- y = int((h-1) - h * ((y + 1.0) % 2.0) / 2.0)
- c = pic.getPixelF( x,y )
- return ( c[0] + c[1] + c[2] ) / 3.0
-
-##-------------------------------------------------------------------------------------
-
-# Transpose noise coords:
-def Trans((x,y,z), size, loc ):
- x = ( x / size[1] / size[0] + loc[0] )
- y = ( y / size[2] / size[0] + loc[1] )
- z = 0.0 #( z / size[3] / size[0] + loc[2] )
- return x,y,z
-
-# Transpose effect coords:
-def Trans_Effect((x,y,z), size, loc ):
- x = ( x * size[1] * size[0] + loc[0] )
- y = ( y * size[2] * size[0] + loc[1] )
- z = 0.0
- return x,y,z
-
-# Height scale:
-def HeightScale( input, iscale, offset, invert ):
- if invert !=0:
- return (1.0-input) * iscale + offset
- else:
- return input * iscale + offset
-
-# dist.
-def Dist(x,y):
- return sqrt( (x*x)+(y*y) )
-
-##-----------------------------------
-# bias types:
-def no_bias(a):
- return a
-def sin_bias(a):
- return 0.5 + 0.5 * sin(a)
-def cos_bias(a):
- return 0.5 + 0.5 * cos(a)
-def tri_bias(a):
- b = 2 * phi
- a = 1 - 2 * abs(floor((a * (1/b))+0.5) - (a*(1/b)))
- return a
-def saw_bias(a):
- b = 2 * phi
- n = int(a/b)
- a -= n * b
- if a < 0: a += b
- return a / b
-# sharpen types:
-def soft(a):
- return a
-def sharp(a):
- return a**0.5
-def sharper(a):
- return sharp(sharp(a))
-Bias_Types = [ sin_bias, cos_bias, tri_bias, saw_bias, no_bias ]
-Sharp_Types = [ soft, sharp, sharper ]
-
-##-----------------------------------
-# clamp height
-def clamp( height, min, max ):
- if ( height < min ): height = min
- if ( height > max ): height = max
- return height
-
-##-----------------------------------
-# Mix modes
-def maximum( a, b ):
- if ( a > b ): b = a
- return b
-def minimum( a, b ):
- if ( a < b ): b = a
- return b
-
-def Mix_Modes( (i,j),(x,y,z) , a,b, mixfactor, mode ):
- a = a * ( 1.0 - mixfactor )
- b = b * ( 1.0 + mixfactor )
- if mode == 0: return ( b ) #0 effect only
- elif mode == 1: return ( a*(1.0-0.5) + (b*0.5) ) #1 mix
- elif mode == 2: return ( a + b ) #2 add
- elif mode == 3: return ( a - b ) #3 sub.
- elif mode == 4: return ( a * b ) #4 mult.
- elif mode == 5: return (abs( a - b )) #5 abs diff.
- elif mode == 6: return 1.0-((1.0-a)*(1.0-b)/1.0) #6 screen
- elif mode == 7: return ( a + b ) % 1.0 #7 addmodulo
- elif mode == 8: return min( a, b ) #8 min.
- elif mode == 9: return max( a, b ) #9 max.
- elif mode == 10: #10 warp: effect
- noise = mixfactor * Noise_Function(x,y,z)
- return Effects( (i,j),(x+noise,y+noise,z) )
- elif mode == 11: #11 warp: noise
- effect = mixfactor * Effects( (i,j),(x,y,z) )
- return Noise_Function( x+effect, y+effect, z )
- else: return a
-
-###----------------------------------------------------------------------
-# Effect functions:
-
-# Effect_Basis_Function:
-def Effect_Basis_Function((x,y), type, bias ):
-
- iscale = 1.0
- offset = 0.0
- ## gradient:
- if type == 0:
- effect = offset + iscale * ( Bias_Types[ bias ]( x + y ) )
- ## waves / bumps:
- if type == 1:
- effect = offset + iscale * 0.5 * ( Bias_Types[ bias ]( x*phi ) + Bias_Types[ bias ]( y*phi ) )
- ## zigzag:
- if type == 2:
- effect = offset + iscale * Bias_Types[ bias ]( offset + iscale * sin( x*phi + sin( y*phi ) ) )
- ## wavy:
- if type == 3:
- effect = offset + iscale * ( Bias_Types[ bias ]( cos( x ) + sin( y ) + cos( x*2+y*2 ) - sin( -x*4+y*4) ) )
- ## sine bump:
- if type == 4:
- effect = offset + iscale * 1-Bias_Types[ bias ](( sin( x*phi ) + sin( y*phi ) ))
- ## dots:
- if type == 5:
- effect = offset + iscale * ( Bias_Types[ bias ](x*phi*2) * Bias_Types[ bias ](y*phi*2) )-0.5
- ## rings / dome:
- if type == 6:
- effect = offset + iscale * ( Bias_Types[ bias ]( 1.0-(x*x+y*y) ) )
- ## spiral:
- if type == 7:
- effect = offset + iscale * Bias_Types[ bias ](( x*sin( x*x+y*y ) + y*cos( x*x+y*y ) ))*0.5
- ## square / piramide:
- if type == 8:
- effect = offset + iscale * Bias_Types[ bias ](1.0-sqrt( (x*x)**10 + (y*y)**10 )**0.1)
- ## blocks:
- if type == 9:
- effect = ( 0.5-max( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) ))
- if effect > 0.0: effect = 1.0
- effect = offset + iscale * effect
- ## grid:
- if type == 10:
- effect = ( 0.025-min( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) ))
- if effect > 0.0: effect = 1.0
- effect = offset + iscale * effect
- ## tech:
- if type == 11:
- a = ( max( Bias_Types[ bias ](x*pi) , Bias_Types[ bias ](y*pi) ))
- b = ( max( Bias_Types[ bias ](x*pi*2+2) , Bias_Types[ bias ](y*pi*2+2) ))
- effect = ( min( Bias_Types[ bias ](a) , Bias_Types[ bias ](b) ))*3.0-2.0
- if effect > 0.5: effect = 1.0
- effect = offset + iscale * effect
-
- ## crackle:
- if type == 12:
- t = turbulence(( x, y, 0 ), 6, 0, 0 ) * 0.25
- effect = vlNoise(( x, y, t ), 0.25, 0, 8 )
- if effect > 0.5: effect = 0.5
- effect = offset + iscale * ( effect )
- ## sparse cracks noise:
- if type == 13:
- effect = 2.5 * abs( noise((x*0.5,y*0.5, 0 ), 1 ) )-0.1
- if effect > 0.25: effect = 0.25
- effect = offset + iscale * ( effect * 2.5 )
- ## shattered rock noise:
- if type == 14:
- effect = 0.5 + noise((x,y,0), 7 )
- if effect > 0.75: effect = 0.75
- effect = offset + iscale * effect
- ## lunar noise:
- if type == 15:
- effect = 0.25 + 1.5 * voronoi(( x+2, y+2, 0 ), 1 )[0][0]
- if effect > 0.5: effect = 0.5
- effect = offset + iscale * ( effect * 2.0 )
- ## cosine noise:
- if type == 16:
- effect = cos( 5*noise(( x, y, 0 ), 0 ) )
- effect = offset + iscale * ( effect*0.5 )
- ## spikey noise:
- if type == 17:
- n = 0.5 + 0.5 * turbulence(( x*5, y*5, 0 ), 8, 0, 0 )
- effect = ( ( n*n )**5 )
- effect = offset + iscale * effect
- ## stone noise:
- if type == 18:
- effect = offset + iscale *( noise((x*2,y*2, 0 ), 0 ) * 1.5 - 0.75)
- ## Flat Turb:
- if type == 19:
- t = turbulence(( x, y, 0 ), 6, 0, 0 )
- effect = t*2.0
- if effect > 0.25: effect = 0.25
- effect = offset + iscale * ( effect )
- ## Flat Voroni:
- if type == 20:
- t = 1-noise(( x, y, 0 ), 3 )
- effect = t*2-1.75
- if effect > 0.25: effect = 0.25
- effect = offset + iscale * ( effect )
-
- if effect < 0.0: effect = 0.0
- return effect
-
-# fractalize Effect_Basis_Function: ------------------------------
-def Effect_Function((x,y), type,bias, turb, depth,frequency,amplitude ):
-
- ## effect distortion:
- if turb != 0.0:
- t = vTurbulence(( x, y, 0 ), 6, 0, 0 )
- x = x + ( 0.5 + 0.5 * t[0] ) * turb
- y = y + ( 0.5 + 0.5 * t[1] ) * turb
-
- result = Effect_Basis_Function((x,y), type, bias )
- ## fractalize effect:
- if depth != 0:
- i=0
- while i < depth:
- i+=1
- x *= frequency
- y *= frequency
- amplitude = amplitude / i
- result += Effect_Basis_Function( (x,y), type, bias ) * amplitude
- return result
-
-###--------------------------------------------------
-# Custom effect:
-def CustomEffect( x,y,z,h ):
- global CustomFX
- try:
- a = eval( CustomFX[0].val )
- b = eval( CustomFX[1].val )
- result = eval( CustomFX[2].val )
- return result
- except:
- return 0.0
-
-###--------------------------------------------------
-## Effect Selector:
-
-def Effects( (i,j),(x,y,z), h=0.0 ):
- global Effect_Type, Effect_Ctrl, iScale, Offset, Invert
- global NSize, Lx, Ly, Lz, Sx, Sy, Sz, marbleTwo, turbTwo, vlnoiTwo, Basis, musgrTwo
-
- x,y,z = Trans_Effect((x,y,z),( NSize[1].val, Sx[1].val, Sy[1].val, 0 ),( Lx[1].val, Ly[1].val, 0 ) )
- basis = Basis[1].val
- if basis == 9: basis = 14
- vbasis = vlnoiTwo[1].val
- if vbasis == 9: vbasis = 14
- if Effect_Ctrl[0].val == 1:
- try: effect = Image_Func( x,y )
- except: effect = 0.0
- elif Effect_Ctrl[0].val == 2: effect = 0.5+0.5*turbulence(( x,y,z ),turbTwo[0].val, turbTwo[1].val, basis, turbTwo[2].val, turbTwo[3].val )
- elif Effect_Ctrl[0].val == 3: effect = 0.5+0.5*vlNoise(( x,y,z ),vlnoiTwo[0].val, vbasis, basis )
- elif Effect_Ctrl[0].val == 4: effect = 0.5*marbleNoise((x,y,z), marbleTwo[0].val, basis, marbleTwo[2].val, marbleTwo[3].val, marbleTwo[4].val, marbleTwo[5].val )
- elif Effect_Ctrl[0].val == 5: effect = 0.5*multiFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )
- elif Effect_Ctrl[0].val == 6: effect = 0.5*ridgedMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis )
- elif Effect_Ctrl[0].val == 7: effect = 0.5*hybridMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis )
- elif Effect_Ctrl[0].val == 8: effect = 0.5*heteroTerrain(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, basis )*0.5
- elif Effect_Ctrl[0].val == 9: effect = 0.5*fBm(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )+0.5
- elif Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31:
- effect = Effect_Function((x,y), Effect_Ctrl[0].val-10, Effect_Ctrl[3].val, Effect_Ctrl[4].val, Effect_Ctrl[5].val, Effect_Ctrl[6].val, Effect_Ctrl[7].val )
- elif Effect_Ctrl[0].val == 31: effect = Effect_Ctrl[8].val * random()
- elif Effect_Ctrl[0].val == 32: effect = Effect_Ctrl[8].val
- elif Effect_Ctrl[0].val == 33: effect = CustomEffect( x,y,z, h )
- effect = HeightScale( effect, iScale[1].val , Offset[1].val, Invert[1].val )
- return effect*2.0
-
-###----------------------------------------------------------------------
-# Noise:
-##-----------------------------------
-
-## voronoi_turbulence:
-def voroTurbMode((x,y,z), voro, mode ):
- if mode == 0: # soft
- return voronoi(( x,y,z ),voro[0], voro[1] )[0][0]
- if mode == 1: # hard
- return ( abs( 0.5-voronoi(( x,y,z ),voro[0], voro[1] )[0][0] ) )+0.5
-def voronoi_turbulence((x,y,z), voro, tur ):
- result = voroTurbMode((x,y,z), voro, tur[1] )
- depth = tur[0]
- amp = tur[2]
- freq = tur[3]
- i=0
- for i in xrange( depth ):
- i+=1
- result += voroTurbMode( ( x*(freq*i), y*(freq*i), z ), voro, tur[1] )* ( amp*0.5/i )
- return (result*4.0-2.0)
-
-## DistortedNoise / vlNoise_turbulence:
-def vlnTurbMode((x,y,z), vlno, basis, mode ):
- if mode == 0: # soft
- return vlNoise(( x,y,z ),vlno[0], vlno[1], basis )
- if mode == 1: # hard
- return ( abs( -vlNoise(( x,y,z ),vlno[0], vlno[1], basis ) ) )
-def vlNoise_turbulence((x,y,z), vlno, tur, basis ):
- result = vlnTurbMode((x,y,z), vlno, basis, tur[1] )
- depth = tur[0]
- amp = tur[2]
- freq = tur[3]
- i=0
- for i in xrange( depth ):
- i+=1
- result += vlnTurbMode( ( x*(freq*i), y*(freq*i), z ), vlno, basis, tur[1] ) * ( amp*0.5/i )
- return result*2.0+0.5
-
-## marbleNoise:
-def marbleNoise( (x,y,z), depth, basis, turb, bias, sharpnes, rescale ):
- m = ( x * rescale + y * rescale + z ) * 5
- height = m + turb * turbulence( ( x ,y ,z ), depth, 0, basis, 0.5, 2.0 )
- height = Bias_Types[ bias ]( height )
- if bias != 4:
- height = Sharp_Types[ sharpnes ]( height )
- return height*2.0
-
-## lava_multiFractal:
-def lava_multiFractal( ( x,y,z ),Ha, La, Oc, distort, Basis ):
- m = multiFractal( ( x,y,z ), Ha, La, Oc, Basis)
- d = m * distort
- m2 = 0.5 * multiFractal( ( x+d,y+d,d*0.5 ), Ha, La, Oc, Basis)
- return (m * m2)**0.5
-
-## slopey_noise:
-def slopey_noise((x,y,z), H, lacunarity, octaves, distort, basis ):
- x=x*2
- y=y*2
- turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.5
- map = 0.5 + noise( ( x+turb, y+turb, z ), basis )
- result = map + turb * distort
- return result
-
-## duo_multiFractal:
-def double_multiFractal((x,y,z), H, lacunarity, octaves, offset, gain, basis ):
- n1 = multiFractal( (x*1.5+1,y*1.5+1,z), 1.0, 1.0, 1.0, basis[0] ) * offset
- n2 = multiFractal( (x-1,y-1,z), H, lacunarity, octaves, basis[1] ) * gain
- result = ( n1*n1 + n2*n2 )*0.5
- return result
-
-## distorted_heteroTerrain:
-def distorted_heteroTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ):
- h1 = ( heteroTerrain((x,y,z), 1.0, 2.0, 1.0, 1.0, basis[0] ) * 0.5 )
- h2 = ( heteroTerrain(( x, y, h1*distort ), H, lacunarity, octaves, offset, basis[1] ) * 0.25 )
- result = ( h1*h1 + h2*h2 )
- return result
-
-## SlickRock:
-def SlickRock((x,y,z), H, lacunarity, octaves, offset, gain, basis ):
- n = multiFractal( (x,y,z), 1.0, 2.0, 1.0, basis[0] )
- r = ridgedMFractal((x,y,n*0.5), H, lacunarity, octaves, offset, gain, basis[1] )*0.5
- return n+(n*r)
-
-## terra_turbulence:
-def terra_turbulence((x,y,z), depth, hard, basis, amp, freq ):
- t2 = turbulence( ( x, y, z ), depth, hard , basis, amp, freq )
- return (t2*t2*t2)+0.5
-
-## rocky_fBm:
-def rocky_fBm((x,y,z), H, lacunarity, octaves, basis ):
- turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.25
- coords = ( x+turb, y+turb, z )
- map = noise( coords, 7 )
- result = map + fBm( coords, H, lacunarity, octaves, basis ) + 1.0
- return result
-
-## Shattered_hTerrain:
-def Shattered_hTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ):
- d = ( turbulence( ( x, y, z ), 6, 0, 0, 0.5, 2.0 ) * 0.5 + 0.5 )*distort*0.25
- t0 = ( turbulence( ( x+d, y+d, z ), 0, 0, 7, 0.5, 2.0 ) + 0.5 )
- t2 = ( heteroTerrain(( x*2, y*2, t0*0.5 ), H, lacunarity, octaves, offset, basis ) )
- return (( t0*t2 )+t2*0.5)*0.75
-
-## vlhTerrain
-def vlhTerrain((x,y,z), H, lacunarity, octaves, offset, basis, vlbasis, distort ):
- ht = heteroTerrain(( x, y, z ), H, lacunarity, octaves, offset, basis )*0.5
- vl = ht * vlNoise((x,y,z), distort, basis, vlbasis )*0.5+0.5
- return vl * ht
-
-####---------------------------------------.
-### StatsByAlt, double terrain basis mode:
-def TerrainBasisMode((x,y,z), basis, mode ):
- if mode == 0: # noise
- return noise((x,y,z),basis)
- if mode == 1: # noise ridged
- return ( 1.0-abs( noise((x,y,z),basis) ) )-0.5
- if mode == 2: # vlNoise
- return vlNoise((x,y,z), 1.0, 0, basis )
- else: # vlNoise ridged
- return ( 1.0-abs( vlNoise((x,y,z), 1.0, 0, basis ) ) )-0.5
-
-#### StatsByAlt terrain:
-def StatsByAltTerrain((x,y,z), exp, lacu, octs, offset, amp, basis, mode ):
- result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
- octs = int( octs )
- i = 0
- for i in xrange( 1, octs ):
- i += 1
- result += result * amp * 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
- x *= lacu
- y *= lacu
- amp /= ( exp * 0.5 ) * i
- return result
-
-##### double terrain:
-def doubleTerrain((x,y,z), exp, lacu, octs, offset, threshold, basis, mode ):
- result = amp = freq = 1.0
- #octs = int( octs )
- offset*=0.5
- i = 1
- signal = result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
- for i in xrange( 1, octs ):
- i += 1
- x = x * lacu
- y = y * lacu
- freq *= lacu
- amp = pow( freq, -exp )
- amp *= i
- weight = signal / threshold
- if weight > 1.0: weight = 1.0
- if weight < 0.0: weigth = 0.0
- signal = weight * 0.5 * ( offset + TerrainBasisMode((x,y,z), basis, mode ) )
- result += amp * signal
- return result * 2.0
-
-##------------------------------------------------------------
-# Noise Functions:
-def Noise_Function(x,y,z):
- global Basis, NType, musgr, vlnoi, voron, turbOne, marbleOne, tBasismod
- global vlBasis, Distort, VFunc, VExp, VDep
- global iScale, Offset, Invert, NSize, Lx, Ly, Sx, Sy
-
- x,y,z = Trans((x,y,z),( NSize[0].val, Sx[0].val, Sy[0].val, 0 ),( Lx[0].val, Ly[0].val, 0 ) )
- basis = Basis[0].val
- if basis == 9: basis = 14
- vbasis = vlnoi[1].val
- if vbasis == 9: vbasis = 14
- if NType.val == 0: z = multiFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )
- elif NType.val == 1: z = ridgedMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis )
- elif NType.val == 2: z = hybridMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis )
- elif NType.val == 3: z = heteroTerrain(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis )*0.5
- elif NType.val == 4: z = fBm(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )+0.5
- elif NType.val == 5: z = turbulence(( x,y,z ),turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )+0.5
- elif NType.val == 6: z = voronoi_turbulence((x,y,z),(voron[0].val,voron[1].val),(turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val) )*0.5+0.5
- elif NType.val == 7: z = vlNoise_turbulence((x,y,z),(vlnoi[0].val,vbasis), (turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val), basis )*0.5+0.5
- elif NType.val == 8: z = noise(( x,y,z ),basis )+0.5
- elif NType.val == 9: z = cellNoise(( x,y,z ))+0.5
- elif NType.val == 10: z = marbleNoise(( x,y,z), marbleOne[0].val, basis, marbleOne[2].val, marbleOne[3].val, marbleOne[4].val, marbleOne[5].val )
- elif NType.val == 11: z = lava_multiFractal(( x,y,z ), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )
- elif NType.val == 12: z = slopey_noise(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )+0.5
- elif NType.val == 13: z = double_multiFractal(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) )
- elif NType.val == 14: z = distorted_heteroTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, (vbasis,basis) )
- elif NType.val == 15: z = SlickRock(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) )
- elif NType.val == 16: z = terra_turbulence(( x,y,z), turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )
- elif NType.val == 17: z = rocky_fBm(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )
- elif NType.val == 18: z = StatsByAltTerrain( (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val*0.5, basis, tBasismod.val )
- elif NType.val == 19: z = doubleTerrain( (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[5].val, basis, tBasismod.val )
- elif NType.val == 20: z = Shattered_hTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, basis )
- elif NType.val == 21: z = vlhTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis, vbasis, vlnoi[0].val )
- else: z = 0.0
- return HeightScale( z, iScale[0].val , Offset[0].val, Invert[0].val )
-
-###----------------------------------------------------------------------
-##-----------------------------------
-# Filter functions:
-
-##-----------------------------------
-# Filter: Clamp height
-def Clamp_Max( height, max ):
- if ( height > max ): height = max
- return height
-def Clamp_Min( height, min ):
- if ( height < min ): height = min
- return height
-
-##-----------------------------------
-# Filters: terrace / posterise / peaked / bias:
-def Def_Filter((x,y,z), input, numb, type ):
- if type == 0:
- s = ( sin( input*numb*phi ) * ( 0.1/numb*phi ) )
- return ( input * (1.0-0.5) + s*0.5 ) * 2.0
- elif type == 1:
- s = -abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) )
- return ( input * (1.0-0.5) + s*0.5 ) * 2.0
- elif type == 2:
- s = abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) )
- return ( input * (1.0-0.5) + s*0.5 ) * 2.0
- elif type == 3:
- numb = numb*0.5
- s = ( int( input*numb ) * 1.0/numb )
- return ( input * (1.0-0.5) + s*0.5 ) * 2.0
- elif type == 4:
- numb = numb*0.5
- s = ( int( input*numb ) * 1.0/numb )
- return ( s ) * 2.0
- elif type == 5:
- s = ( sin( input*(2*numb)*phi ) * ( 0.1/(2*numb)*phi ) )
- l = ( input * (1.0-0.5) + s*0.5 ) * 2.0
- p = ( ( l*numb*0.25 ) * ( l*numb*0.25 ) )**2
- return ( l * (1.0-0.5) + p*0.5 ) * 2.0
- elif type == 6:
- return ( input*numb*0.25 )**4
- elif type == 7:
- return 2.0-exp( 1.0-(input*numb/3.0) )
- elif type == 8:
- return sin_bias( input*numb )*2.0
- elif type == 9:
- return cos_bias( input*numb )*2.0
- elif type == 10:
- return tri_bias( input*numb )*2.0
- elif type == 11:
- return saw_bias( input*numb )*2.0
- elif type == 12:
- return Clamp_Max( input, numb )
- else:
- return input
-
-##-----------------------------------
-# Filter: Edge falloff
-def EdgeFalloff( (x,y,z), height, type ):
- global Falloff, iScale, Offset
-
- x = x / Falloff[1].val
- y = y / Falloff[2].val
-
- if Falloff[3].val != 0:
- sealevel = (Min.val-Offset[2].val)*2.0/iScale[2].val
- else:
- sealevel = 0.0
-
- falltypes = ( 0, sqrt(x*x+y*y), sqrt((x*x)**2+(y*y)**2), sqrt((x*x)**10+(y*y)**10), sqrt(y*y), sqrt(x*x), abs(x-y), abs(x+y), ((x*x)**10+(y*y)**10)**0.1, ((x*x)+(y*y)) )
-
- dist = falltypes[ type ]
- if Falloff[4].val != 0:
- dist = 1.0 - dist
- radius = 1.0
- height = height - sealevel
- if( dist < radius ):
- dist = dist / radius
- dist = ( (dist) * (dist) * ( 3-2*(dist) ) )
- height = ( height - height * dist ) + sealevel
- else:
- height = sealevel
-
- if Falloff[3].val != 0:
- height = Clamp_Min( height, sealevel )
- else:
- height = Clamp_Min( height, Min.val )
-
- return height
-
-##-----------------------------------
-# Filter: Custom height filter:
-def CustomFilter( x,y,z, h ):
- global CustomFilt
- try:
- a = eval(CustomFilt[0].val)
- b = eval(CustomFilt[1].val)
- result = eval(CustomFilt[2].val)
- return result
- except:
- return 0.0
-
-#####-------------------------------------------------------------------------------------#####
-####-------------------------------------------------------------------------------------####
-### Combine Functions: (get noise, Add effect, filter height and return result) ###
-##-------------------------------------------------------------------------------------##
-
-def Combine_Functions( (i,j),(x,y,z) ):
- global Effect_Ctrl, Blend_Effect, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
- global iScale, Offset, Invert, Min, Max, Falloff
-
- # get noise height:
- height = Noise_Function(x,y,0.0)
-
- ### Filter On
- if Filter_Mode.val !=0:
- ### 0= Default Filter Order: Noise>Effect>Filter ---------------------
- if Filter_Order.val ==0:
- # mix noise with effect:
- if Effect_Ctrl[0].val !=0:
- height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
- # edge fallof:
- if Falloff[0].val !=0:
- height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
- #else: pass
-
- if Filter_Mode.val !=0:
- # height Def_Filter (Terrace/peaked/bias):
- if Filter_Mode.val ==1:
- height = Def_Filter((x,y,z), height, Def_Filter_Ctrl[ 1 ].val, Def_Filter_Ctrl[ 0 ].val )
-
- ## 'IPOCurve' height filter:
- elif Filter_Mode.val ==2:
- try:
- height = selectedcurve.evaluate( 1 + ( height*Ipo_Filter_Ctrl[2].val/2 ) )*2.0/Ipo_Filter_Ctrl[3].val
- except:
- height = height
-
- ## Custom filter:
- elif Filter_Mode.val ==3:
- height = CustomFilter( x,y,z, height )
-
- ### 1= Changed Filter Order: Noise>Filter>Effect ---------------------
- if Filter_Order.val !=0:
- # mix noise with effect:
- if Effect_Ctrl[0].val !=0:
- height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
- # edge fallof:
- if Falloff[0].val !=0:
- height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
- #else: pass
-
- ### Filter Off ---------------------
- else:
- # mix noise with effect:
- if Effect_Ctrl[0].val !=0:
- height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
- # edge fallof:
- if Falloff[0].val !=0:
- height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
-
- # height scale:
- height = HeightScale( height, 0.5*iScale[2].val , Offset[2].val, Invert[2].val )
-
- # clamp height min. max.:
- if Falloff[0].val !=1:
- height = Clamp_Min( height, Min.val )
- height = Clamp_Max( height, Max.val )
-
- # return height:
- return height
-
-
-#------------------------------------------------------------
-##------------------------------------------------------------
-### Render Noise to a Image('NAME') (you must create one first)
-##------------------------------------------------------------
-#------------------------------------------------------------
-
-def HeightFieldImage():
- global PreView, previewname
-
- iname = previewname.val
- try:
- pic = Image.Get( iname )
- except:
- #print iname, ' No Image with this name'
- PupMenu( 'No Image with this name' )
- return
- res = pic.getMaxXY()
- for i in xrange( res[0] ):
- x = i - (res[0]) / 2.0
- x = (x*2.0) / (res[0])
- for j in xrange( res[1] ):
- y = j - (res[1]) / 2.0
- y = (y*2.0) / (res[1])
- height = PreView[2].val + PreView[1].val * Combine_Functions( (i,j),(x,y,0) )
- if height > 1.0: height = 1.0
- if height < 0.0: height = 0.0
- pic.setPixelF( i, j, ( height,height,height, 1.0 ) )
-
-
-#------------------------------------------------------------
-##------------------------------------------------------------
-### Mesh
-##------------------------------------------------------------
-#------------------------------------------------------------
-
-#------------------------------------------------------------
-## Mesh: make new grid
-###------------------------------------------------------------
-
-def MakeGridMesh( RESOL=32, NAME='GridMesh', CURSORPOS=0, SCENE=None ):
- # scene, object, mesh ---------------------------------------
- if not SCENE:
- SCENE = Blender.Scene.GetCurrent()
- SCENE.objects.selected=[]
- newme = Blender.Mesh.New( NAME )
- newob = SCENE.objects.new( newme, NAME )
- n = RESOL
- # verts ---------------------------------------
- v=[]
- for i in xrange( n ):
- x = i-(n-1)/2.0
- x = x*2.0/(n-1)
- for j in xrange( n ):
- y = j-(n-1)/2.0
- y = y*2.0/(n-1)
- v.append( [ x, y, 0 ] )
- newme.verts.extend(v)
- # faces ---------------------------------------
- f=[]
- for i in xrange( n-1 ):
- for j in xrange( n-1 ):
- f.append( [ i*n+j,\
- (i+1)*n+j,\
- (i+1)*n+j+1,\
- i*n+j+1 ] )
-
- newme.faces.extend(f, smooth=True)
- #---------------------------------------
- newme.calcNormals()
- #---------------------------------------
- if CURSORPOS !=0:
- newob.loc = Window.GetCursorPos()
- newob.select(1)
-
-#------------------------------------------------------------
-## Mesh: Grid vert displace / update terrain
-###------------------------------------------------------------
-
-def displace( OB, ME, WORLD=0 ):
- if WORLD == 1:
- wx,wy,wz = OB.getLocation( 'worldspace' )
- elif WORLD ==2:
- l = OB.getLocation( 'worldspace' )
- w = Window.GetCursorPos()
- wx,wy,wz = l[0]-w[0], l[1]-w[1], l[2]-w[2]
- else:
- wx,wy,wz = 0,0,0
-
- for v in ME.verts:
- co = v.co
- co[2] = Combine_Functions( (co[0]+wx,co[1]+wy),(co[0]+wx, co[1]+wy, 0.0+wz) )
- ME.update()
- ME.calcNormals()
- #OB.makeDisplayList()
-
-
-#----------------------------------------------------------------------------------------------------
-##----------------------------------------------------------------------------------------------------
-###----------------------------------------------------------------------------------------------------
-####----------------------------------------------------------------------------------------------------
-###----------------------------------------------------------------------------------------------------
-## Do_it:
-#--------------------------------------
-
-#--------------------------------------
-def do_it():
- global PreView, actme, actob, WorldSpaceCo
- if actme !=[]:
- if print_time !=0:
- t= sys.time()
- Window.WaitCursor(1)
- in_editmode = Window.EditMode()
- if in_editmode: Window.EditMode(0)
- if PreView[0].val != 0:
- do_it_preview()
- displace( actob[0], actme[0], WorldSpaceCo.val )
- Window.RedrawAll()
- else:
- displace( actob[0], actme[0], WorldSpaceCo.val )
- Window.RedrawAll()
- if in_editmode: Window.EditMode(1)
- Window.WaitCursor(0)
- if print_time !=0:
- print 'Generate Mesh: done in %.6f' % (sys.time()-t)
-
-#--------------------------------------
-def do_it_random():
- global PreView, actme, actob
- if actme !=[]:
- if print_time !=0:
- t= sys.time()
- Window.WaitCursor(1)
- in_editmode = Window.EditMode()
- if in_editmode: Window.EditMode(0)
- randomiseNoise()
- if PreView[0].val != 0:
- do_it_preview()
- displace( actob[0], actme[0], WorldSpaceCo.val )
- Window.RedrawAll()
- else:
- displace( actob[0], actme[0], WorldSpaceCo.val )
- Window.RedrawAll()
- if in_editmode: Window.EditMode(1)
- Window.WaitCursor(0)
- if print_time !=0:
- print 'Generate Mesh: done in %.6f' % (sys.time()-t)
-
-#--------------------------------------
-def do_it_preview():
- if print_time !=0:
- t= sys.time()
- HeightFieldImage()
- Window.RedrawAll()
- if print_time !=0:
- print 'Generate Image: done in %.6f' % (sys.time()-t)
-
-###---------------------------------------------------------
-###---------------------------------------------------------
-## load and save:
-#-------------------------
-
-def callback( filename ):
- txtFile.val = filename
- Register(drawgui, events, bevents)
-def writeln(f,x):
- f.write(str(x))
- f.write("\n")
-def readint(f):
- return int(f.readline())
-def readfloat(f):
- return float(f.readline())
-def readstr(f):
- s = (f.readline())
- return strip(s)
-
-#--------------------------------------------------
-# Save settings to .ant file
-def SavePreset(FName):
- global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly
- global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo
- global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
- global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo
-
- try:
- f = open(FName,'w')
- writeln(f,CurVersion)
- except:
- filemessage = "Unable to save file."
- return
-
- writeln(f,fileinfo)
- writeln(f,iScale[0].val)
- writeln(f,iScale[1].val)
- writeln(f,iScale[2].val)
- writeln(f,Offset[0].val)
- writeln(f,Offset[1].val)
- writeln(f,Offset[2].val)
- writeln(f,Invert[0].val)
- writeln(f,Invert[1].val)
- writeln(f,Invert[2].val)
- writeln(f,NSize[0].val)
- writeln(f,NSize[1].val)
- writeln(f,Sx[0].val)
- writeln(f,Sx[1].val)
- writeln(f,Sy[0].val)
- writeln(f,Sy[1].val)
- writeln(f,Lx[0].val)
- writeln(f,Lx[1].val)
- writeln(f,Ly[0].val)
- writeln(f,Ly[1].val)
- writeln(f,NType.val)
- writeln(f,Basis[0].val)
- writeln(f,Basis[1].val)
- writeln(f,musgr[0].val)
- writeln(f,musgr[1].val)
- writeln(f,musgr[2].val)
- writeln(f,musgr[3].val)
- writeln(f,musgr[4].val)
- writeln(f,musgr[5].val)
- writeln(f,tBasismod.val)
- writeln(f,vlnoi[0].val)
- writeln(f,vlnoi[1].val)
- writeln(f,vlnoiTwo[0].val)
- writeln(f,vlnoiTwo[1].val)
- writeln(f,voron[0].val)
- writeln(f,voron[1].val)
- writeln(f,turbOne[0].val)
- writeln(f,turbOne[1].val)
- writeln(f,turbOne[2].val)
- writeln(f,turbOne[3].val)
- writeln(f,turbTwo[0].val)
- writeln(f,turbTwo[1].val)
- writeln(f,turbTwo[2].val)
- writeln(f,turbTwo[3].val)
- writeln(f,marbleOne[0].val)
- writeln(f,marbleOne[1].val)
- writeln(f,marbleOne[2].val)
- writeln(f,marbleOne[3].val)
- writeln(f,marbleOne[4].val)
- writeln(f,marbleOne[5].val)
- writeln(f,marbleTwo[0].val)
- writeln(f,marbleTwo[1].val)
- writeln(f,marbleTwo[2].val)
- writeln(f,marbleTwo[3].val)
- writeln(f,marbleTwo[4].val)
- writeln(f,marbleTwo[5].val)
- writeln(f,musgrTwo[0].val)
- writeln(f,musgrTwo[1].val)
- writeln(f,musgrTwo[2].val)
- writeln(f,musgrTwo[3].val)
- writeln(f,musgrTwo[4].val)
- writeln(f,effect_image)
- writeln(f,Effect_Ctrl[0].val)
- writeln(f,Effect_Ctrl[1].val)
- writeln(f,Effect_Ctrl[2].val)
- writeln(f,Effect_Ctrl[3].val)
- writeln(f,Effect_Ctrl[4].val)
- writeln(f,Effect_Ctrl[5].val)
- writeln(f,Effect_Ctrl[6].val)
- writeln(f,Effect_Ctrl[7].val)
- writeln(f,Effect_Ctrl[8].val)
- writeln(f,CustomFX[0].val)
- writeln(f,CustomFX[1].val)
- writeln(f,CustomFX[2].val)
- writeln(f,Min.val)
- writeln(f,Max.val)
- writeln(f,Falloff[0].val)
- writeln(f,Falloff[1].val)
- writeln(f,Falloff[2].val)
- writeln(f,Falloff[3].val)
- writeln(f,Falloff[4].val)
- writeln(f,Filter_Mode.val)
- writeln(f,Filter_Order.val)
- writeln(f,CustomFilt[0].val)
- writeln(f,CustomFilt[1].val)
- writeln(f,CustomFilt[2].val)
- writeln(f,Def_Filter_Ctrl[0].val)
- writeln(f,Def_Filter_Ctrl[1].val)
- writeln(f,Ipo_Filter_Ctrl[0].val)
- writeln(f,Ipo_Filter_Ctrl[1].val)
- writeln(f,Ipo_Filter_Ctrl[2].val)
- writeln(f,Ipo_Filter_Ctrl[3].val)
- writeln(f,RandMod.val)
- writeln(f,RSeed.val)
- writeln(f,rand_H.val)
- writeln(f,rand_I.val)
- writeln(f,rand_S.val)
- writeln(f,rand_L.val)
- filemessage = 'Settings saved to file.'
- f.close()
-
-#--------------------------------------------------
-# load settings from .ant file
-def LoadPreset(FName):
- global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly
- global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo
- global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
- global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo
-
- try:
- f = open(FName,'r')
- FVersion = readstr(f)
- except:
- filemessage = "Unable to open file."
- return
-
- fileinfo = readstr(f)
- iScale[0].val = readfloat(f)
- iScale[1].val = readfloat(f)
- iScale[2].val = readfloat(f)
- Offset[0].val = readfloat(f)
- Offset[1].val = readfloat(f)
- Offset[2].val = readfloat(f)
- Invert[0].val = readint(f)
- Invert[1].val = readint(f)
- Invert[2].val = readint(f)
- NSize[0].val = readfloat(f)
- NSize[1].val = readfloat(f)
- Sx[0].val = readfloat(f)
- Sx[1].val = readfloat(f)
- Sy[0].val = readfloat(f)
- Sy[1].val = readfloat(f)
- Lx[0].val = readfloat(f)
- Lx[1].val = readfloat(f)
- Ly[0].val = readfloat(f)
- Ly[1].val = readfloat(f)
- NType.val = readint(f)
- Basis[0].val = readint(f)
- Basis[1].val = readint(f)
- musgr[0].val = readfloat(f)
- musgr[1].val = readfloat(f)
- musgr[2].val = readint(f)
- musgr[3].val = readfloat(f)
- musgr[4].val = readfloat(f)
- musgr[5].val = readfloat(f)
- tBasismod.val = readint(f)
- vlnoi[0].val = readfloat(f)
- vlnoi[1].val = readint(f)
- vlnoiTwo[0].val = readfloat(f)
- vlnoiTwo[1].val = readint(f)
- voron[0].val = readint(f)
- voron[1].val = readfloat(f)
- turbOne[0].val = readint(f)
- turbOne[1].val = readint(f)
- turbOne[2].val = readfloat(f)
- turbOne[3].val = readfloat(f)
- turbTwo[0].val = readint(f)
- turbTwo[1].val = readint(f)
- turbTwo[2].val = readfloat(f)
- turbTwo[3].val = readfloat(f)
- marbleOne[0].val = readint(f)
- marbleOne[1].val = readint(f)
- marbleOne[2].val = readfloat(f)
- marbleOne[3].val = readint(f)
- marbleOne[4].val = readint(f)
- marbleOne[5].val = readfloat(f)
- marbleTwo[0].val = readint(f)
- marbleTwo[1].val = readint(f)
- marbleTwo[2].val = readfloat(f)
- marbleTwo[3].val = readint(f)
- marbleTwo[4].val = readint(f)
- marbleTwo[5].val = readfloat(f)
- musgrTwo[0].val = readfloat(f)
- musgrTwo[1].val = readfloat(f)
- musgrTwo[2].val = readint(f)
- musgrTwo[3].val = readfloat(f)
- musgrTwo[4].val = readfloat(f)
- effect_image = readstr(f)
- Effect_Ctrl[0].val = readint(f)
- Effect_Ctrl[1].val = readint(f)
- Effect_Ctrl[2].val = readfloat(f)
- Effect_Ctrl[3].val = readint(f)
- Effect_Ctrl[4].val = readfloat(f)
- Effect_Ctrl[5].val = readint(f)
- Effect_Ctrl[6].val = readfloat(f)
- Effect_Ctrl[7].val = readfloat(f)
- Effect_Ctrl[8].val = readfloat(f)
- CustomFX[0].val = readstr(f)
- CustomFX[1].val = readstr(f)
- CustomFX[2].val = readstr(f)
- Min.val = readfloat(f)
- Max.val = readfloat(f)
- Falloff[0].val = readint(f)
- Falloff[1].val = readfloat(f)
- Falloff[2].val = readfloat(f)
- Falloff[3].val = readint(f)
- Falloff[4].val = readint(f)
- Filter_Mode.val = readint(f)
- Filter_Order.val = readint(f)
- CustomFilt[0].val = readstr(f)
- CustomFilt[1].val = readstr(f)
- CustomFilt[2].val = readstr(f)
- Def_Filter_Ctrl[0].val = readint(f)
- Def_Filter_Ctrl[1].val = readfloat(f)
- Ipo_Filter_Ctrl[0].val = readstr(f)
- Ipo_Filter_Ctrl[1].val = readint(f)
- Ipo_Filter_Ctrl[2].val = readfloat(f)
- Ipo_Filter_Ctrl[3].val = readfloat(f)
- RandMod.val = readint(f)
- RSeed.val = readint(f)
- rand_H.val = readint(f)
- rand_I.val = readint(f)
- rand_S.val = readint(f)
- rand_L.val = readint(f)
- filemessage = 'Settings loaded from file.'
- f.close()
-
-##---------------------------------------------------------------------------
-# Register:
-
-Register( drawgui, events, bevents )
-###--------------------------------------------------------------------------
- \ No newline at end of file
diff --git a/release/ui/buttons_data_modifier.py b/release/ui/buttons_data_modifier.py
index ecb0590f8e5..5635529d90e 100644
--- a/release/ui/buttons_data_modifier.py
+++ b/release/ui/buttons_data_modifier.py
@@ -19,9 +19,9 @@ class DATA_PT_modifiers(DataButtonsPanel):
row.itemL();
for md in ob.modifiers:
- box = layout.template_modifier(md)
+ box = layout.template_modifier(context, md)
- if box:
+ if md.expanded:
if md.type == 'ARMATURE':
self.armature(box, md)
if md.type == 'ARRAY':
@@ -99,7 +99,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
if md.fit_type == 'FIT_LENGTH':
layout.itemR(md, "length")
if md.fit_type == 'FIT_CURVE':
- layout.itemR(md, "curve")
+ layout.itemR(md, "curve")
layout.itemS()
@@ -194,7 +194,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemL(text="See Collision panel.")
def curve(self, layout, md):
- layout.itemR(md, "object")
+ layout.itemR(md, "curve")
layout.itemR(md, "vertex_group")
layout.itemR(md, "deform_axis")
@@ -245,7 +245,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
# Missing: "Reset" and "Recenter"
def lattice(self, layout, md):
- layout.itemR(md, "object")
+ layout.itemR(md, "lattice")
layout.itemR(md, "vertex_group")
def mask(self, layout, md):
@@ -257,7 +257,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "inverse")
def mesh_deform(self, layout, md):
- layout.itemR(md, "object")
+ layout.itemR(md, "mesh")
layout.itemR(md, "vertex_group")
layout.itemR(md, "invert")
diff --git a/release/ui/space_sequencer.py b/release/ui/space_sequencer.py
deleted file mode 100644
index 94858db81ad..00000000000
--- a/release/ui/space_sequencer.py
+++ /dev/null
@@ -1,559 +0,0 @@
-
-import bpy
-
-def act_strip(context):
- try: return context.scene.sequence_editor.active_strip
- except: return None
-
-# Header
-class SEQUENCER_HT_header(bpy.types.Header):
- __space_type__ = "SEQUENCE_EDITOR"
- __idname__ = "SEQUENCE_HT_header"
-
- def draw(self, context):
-
- st = context.space_data
- layout = self.layout
-
- layout.template_header(context)
-
- if context.area.show_menus:
- row = layout.row()
- row.itemM(context, "SEQUENCER_MT_view")
-
- row.itemR(st, "display_mode")
-
- layout.itemS()
-
- if st.display_mode == 'SEQUENCER':
- row.itemM(context, "SEQUENCER_MT_select")
- row.itemM(context, "SEQUENCER_MT_marker")
- row.itemM(context, "SEQUENCER_MT_add")
- row.itemM(context, "SEQUENCER_MT_strip")
- layout.itemS()
- row.itemO("SEQUENCER_OT_reload")
- else:
- row.itemR(st, "display_channel") # text="Chan"
-
-class SEQUENCER_MT_view(bpy.types.Menu):
- __space_type__ = "SEQUENCE_EDITOR"
- __label__ = "View (TODO)"
-
- def draw(self, context):
- layout = self.layout
- st = context.space_data
-
- layout.column()
-
- """
- uiBlock *block= uiBeginBlock(C, ar, "seq_viewmenu", UI_EMBOSSP);
- short yco= 0, menuwidth=120;
-
- if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
- "Play Back Animation "
- "in all Sequence Areas|Alt A", 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
- }
- else {
- uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL,
- "Grease Pencil...", 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
- uiDefMenuSep(block);
-
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
- "Play Back Animation "
- "in this window|Alt A", 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
- }
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
- "Play Back Animation in all "
- "3D Views and Sequence Areas|Alt Shift A",
- 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
-
- """
- layout.itemS()
- layout.itemO("SEQUENCER_OT_view_all")
- layout.itemO("SEQUENCER_OT_view_selected")
- layout.itemS()
- """
-
-
- /* Lock Time */
- uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
- "Lock Time to Other Windows|", 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
-
- /* Draw time or frames.*/
- uiDefMenuSep(block);
- """
-
- layout.itemR(st, "draw_frames")
-
- """
- if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,0, "");
- else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
-
- """
-
-class SEQUENCER_MT_select(bpy.types.Menu):
- __space_type__ = "SEQUENCE_EDITOR"
- __label__ = "Select"
-
- def draw(self, context):
- layout = self.layout
- st = context.space_data
-
- layout.column()
- layout.item_enumO("SEQUENCER_OT_select_active_side", "side", 'LEFT', text="Strips to the Left")
- layout.item_enumO("SEQUENCER_OT_select_active_side", "side", 'RIGHT', text="Strips to the Right")
- layout.itemS()
- layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'BOTH', text="Surrounding Handles")
- layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'LEFT', text="Left Handle")
- layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'RIGHT', text="Right Handle")
- layout.itemS()
- layout.itemO("SEQUENCER_OT_select_linked")
- layout.itemO("SEQUENCER_OT_select_all_toggle")
- layout.itemO("SEQUENCER_OT_select_invert")
-
-class SEQUENCER_MT_marker(bpy.types.Menu):
- __space_type__ = "SEQUENCE_EDITOR"
- __label__ = "Marker (TODO)"
-
- def draw(self, context):
- layout = self.layout
- st = context.space_data
-
- layout.column()
- layout.itemO("SEQUENCER_OT_sound_strip_add", text="Add Marker|Ctrl Alt M")
- layout.itemO("SEQUENCER_OT_sound_strip_add", text="Duplicate Marker|Ctrl Shift D")
- layout.itemO("SEQUENCER_OT_sound_strip_add", text="Delete Marker|Shift X")
- layout.itemS()
- layout.itemO("SEQUENCER_OT_sound_strip_add", text="(Re)Name Marker|Ctrl M")
- layout.itemO("SEQUENCER_OT_sound_strip_add", text="Grab/Move Marker|Ctrl G")
- layout.itemS()
- layout.itemO("SEQUENCER_OT_sound_strip_add", text="Transform Markers") # toggle, will be rna - (sseq->flag & SEQ_MARKER_TRANS)
-
-class SEQUENCER_MT_add(bpy.types.Menu):
- __space_type__ = "SEQUENCE_EDITOR"
- __label__ = "Add"
-
- def draw(self, context):
- layout = self.layout
- st = context.space_data
-
- layout.column()
- layout.itemO("SEQUENCER_OT_scene_strip_add", text="Scene")
- layout.itemO("SEQUENCER_OT_movie_strip_add", text="Movie")
- layout.item_booleanO("SEQUENCER_OT_movie_strip_add", "sound", True, text="Movie & Sound") # FFMPEG ONLY
- layout.itemO("SEQUENCER_OT_image_strip_add", text="Image")
- layout.itemO("SEQUENCER_OT_sound_strip_add", text="Sound (Ram)")
- layout.item_booleanO("SEQUENCER_OT_sound_strip_add", "hd", True, text="Sound (Streaming)") # FFMPEG ONLY
-
- layout.itemM(context, "SEQUENCER_MT_add_effect")
-
-
-class SEQUENCER_MT_add_effect(bpy.types.Menu):
- __space_type__ = "SEQUENCE_EDITOR"
- __label__ = "Effect Strip..."
-
- def draw(self, context):
- layout = self.layout
- st = context.space_data
-
- self.layout.column()
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ADD')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'SUBTRACT')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ALPHA_OVER')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ALPHA_UNDER')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'GAMMA_CROSS')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'MULTIPLY')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'OVER_DROP')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'PLUGIN')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'WIPE')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'GLOW')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'TRANSFORM')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'COLOR')
- self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'SPEED')
-
-class SEQUENCER_MT_strip(bpy.types.Menu):
- __space_type__ = "SEQUENCE_EDITOR"
- __label__ = "Strip"
-
- def draw(self, context):
- layout = self.layout
- st = context.space_data
-
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.column()
- layout.item_enumO("TFM_OT_transform", "mode", 'TRANSLATION', text="Grab/Move")
- layout.item_enumO("TFM_OT_transform", "mode", 'TIME_EXTEND', text="Grab/Extend from frame")
- # uiItemO(layout, NULL, 0, "SEQUENCER_OT_strip_snap"); // TODO - add this operator
- layout.itemS()
-
- layout.item_enumO("SEQUENCER_OT_cut", "type", 'HARD', text="Cut (hard) at frame")
- layout.item_enumO("SEQUENCER_OT_cut", "type", 'SOFT', text="Cut (soft) at frame")
- layout.itemO("SEQUENCER_OT_images_separate")
- layout.itemS()
-
- layout.itemO("SEQUENCER_OT_duplicate_add")
- layout.itemO("SEQUENCER_OT_delete")
-
- strip = act_strip(context)
-
- if strip:
- stype = strip.type
-
- if stype=='EFFECT':
- layout.itemS()
- layout.itemO("SEQUENCER_OT_effect_change")
- layout.itemO("SEQUENCER_OT_effect_reassign_inputs")
- elif stype=='IMAGE':
- layout.itemS()
- layout.itemO("SEQUENCER_OT_image_change")
- elif stype=='SCENE':
- layout.itemS()
- layout.itemO("SEQUENCER_OT_scene_change", text="Change Scene")
- elif stype=='MOVIE':
- layout.itemS()
- layout.itemO("SEQUENCER_OT_movie_change")
-
- layout.itemS()
-
- layout.itemO("SEQUENCER_OT_meta_make")
- layout.itemO("SEQUENCER_OT_meta_separate")
-
- #if (ed && (ed->metastack.first || (ed->act_seq && ed->act_seq->type == SEQ_META))) {
- # uiItemS(layout);
- # uiItemO(layout, NULL, 0, "SEQUENCER_OT_meta_toggle");
- #}
-
- layout.itemS()
- layout.itemO("SEQUENCER_OT_reload")
- layout.itemS()
- layout.itemO("SEQUENCER_OT_lock")
- layout.itemO("SEQUENCER_OT_unlock")
- layout.itemO("SEQUENCER_OT_mute")
- layout.itemO("SEQUENCER_OT_unmute")
-
- layout.item_enumO("SEQUENCER_OT_mute", property="type", value='UNSELECTED', text="Mute Deselected Strips")
-
- layout.itemO("SEQUENCER_OT_snap")
-
-# Panels
-class SequencerButtonsPanel(bpy.types.Panel):
- __space_type__ = "SEQUENCE_EDITOR"
- __region_type__ = "UI"
-
- def poll(self, context):
- return context.space_data.display_mode == 'SEQUENCER' and act_strip(context) != None
-
-class SequencerButtonsPanel_Output(bpy.types.Panel):
- __space_type__ = "SEQUENCE_EDITOR"
- __region_type__ = "UI"
-
- def poll(self, context):
- return context.space_data.display_mode != 'SEQUENCER'
-
-class SEQUENCER_PT_edit(SequencerButtonsPanel):
- __label__ = "Edit Strip"
- __idname__ = "SEQUENCER_PT_edit"
-
- def draw(self, context):
- layout = self.layout
-
- strip = act_strip(context)
-
- layout.itemR(strip, "name")
-
- layout.itemR(strip, "type")
-
- layout.itemR(strip, "blend_mode")
-
- layout.itemR(strip, "blend_opacity", text="Opacity", slider=True)
-
- split = layout.split()
-
- col = split.column()
- col.itemR(strip, "mute")
- col.itemR(strip, "lock")
- col.itemR(strip, "frame_locked")
-
- col = split.column()
- col.itemR(strip, "channel")
- col.itemR(strip, "start_frame")
- col.itemR(strip, "length")
-
- split = layout.split()
-
- col = split.column()
- col.itemR(strip, "start_offset")
- col.itemR(strip, "start_still")
-
- col = split.column()
- col.itemR(strip, "end_offset")
- col.itemR(strip, "end_still")
-
-class SEQUENCER_PT_effect(SequencerButtonsPanel):
- __label__ = "Effect Strip"
- __idname__ = "SEQUENCER_PT_effect"
-
- def poll(self, context):
- if context.space_data.display_mode != 'SEQUENCER':
- return False
-
- strip = act_strip(context)
- if not strip:
- return False
-
- return strip.type in ('COLOR', 'WIPE', 'GLOW', 'SPEED', 'TRANSFORM')
-
- def draw(self, context):
- layout = self.layout
-
- strip = act_strip(context)
-
- if strip.type == 'COLOR':
- layout.itemR(strip, "color")
-
- elif strip.type == 'WIPE':
- row = layout.row()
- row.itemL(text="Transition Type:")
- row.itemL(text="Direction:")
-
- row = layout.row()
- row.itemR(strip, "transition_type", text="")
- row.itemR(strip, "direction", text="")
-
- row = layout.row()
- row.itemR(strip, "blur_width")
- if strip.transition_type in ('SINGLE', 'DOUBLE'):
- row.itemR(strip, "angle")
-
- elif strip.type == 'GLOW':
- flow = layout.column_flow()
- flow.itemR(strip, "threshold")
- flow.itemR(strip, "clamp")
- flow.itemR(strip, "boost_factor")
- flow.itemR(strip, "blur_distance")
-
- row = layout.row()
- row.itemR(strip, "quality", slider=True)
- row.itemR(strip, "only_boost")
-
- elif strip.type == 'SPEED':
- layout.itemR(strip, "global_speed")
-
- flow = layout.column_flow()
- flow.itemR(strip, "curve_velocity")
- flow.itemR(strip, "curve_compress_y")
- flow.itemR(strip, "frame_blending")
-
- elif strip.type == 'TRANSFORM':
- row = layout.row()
- row.itemL(text="Interpolation:")
- row.itemL(text="Translation Unit:")
-
- row = layout.row()
- row.itemR(strip, "interpolation", text="")
- row.itemR(strip, "translation_unit", text="")
-
- split = layout.split()
-
- col = split.column()
- sub = col.column(align=True)
- sub.itemL(text="Position X:")
- sub.itemR(strip, "translate_start_x", text="Start")
- sub.itemR(strip, "translate_end_x", text="End")
-
- sub = col.column(align=True)
- sub.itemL(text="Scale X:")
- sub.itemR(strip, "scale_start_x", text="Start")
- sub.itemR(strip, "scale_end_x", text="End")
-
- sub = col.column(align=True)
- sub.itemL(text="Rotation:")
- sub.itemR(strip, "rotation_start", text="Start")
- sub.itemR(strip, "rotation_end", text="End")
-
- col = split.column()
- sub = col.column(align=True)
- sub.itemL(text="Position Y:")
- sub.itemR(strip, "translate_start_y", text="Start")
- sub.itemR(strip, "translate_end_y", text="End")
-
- sub = col.column(align=True)
- sub.itemL(text="Scale Y:")
- sub.itemR(strip, "scale_start_y", text="Start")
- sub.itemR(strip, "scale_end_y", text="End")
-
-class SEQUENCER_PT_input(SequencerButtonsPanel):
- __label__ = "Strip Input"
- __idname__ = "SEQUENCER_PT_input"
-
- def poll(self, context):
- if context.space_data.display_mode != 'SEQUENCER':
- return False
-
- strip = act_strip(context)
- if not strip:
- return False
-
- return strip.type in ('MOVIE', 'IMAGE', 'SOUND')
-
- def draw(self, context):
- layout = self.layout
-
- strip = act_strip(context)
-
- split = layout.split(percentage=0.3)
- sub = split.column()
- sub.itemL(text="Directory:")
- sub = split.column()
- sub.itemR(strip, "directory", text="")
-
- # Current element for the filename
- split = layout.split(percentage=0.3)
- sub = split.column()
- sub.itemL(text="File Name:")
- sub = split.column()
-
- elem = strip.getStripElem(context.scene.current_frame)
- if elem:
- sub.itemR(elem, "filename", text="") # strip.elements[0] could be a fallback
-
- layout.itemR(strip, "use_translation")
- if strip.transform:
- flow = layout.column_flow()
- flow.active = strip.use_translation
- flow.itemR(strip.transform, "offset_x")
- flow.itemR(strip.transform, "offset_y")
-
-
- layout.itemR(strip, "use_crop")
- if strip.crop:
- flow = layout.column_flow()
- flow.active = strip.use_crop
- flow.itemR(strip.crop, "top")
- flow.itemR(strip.crop, "left")
- flow.itemR(strip.crop, "bottom")
- flow.itemR(strip.crop, "right")
-
- layout.itemR(strip, "animation_start_offset")
- layout.itemR(strip, "animation_end_offset")
-
-
-class SEQUENCER_PT_filter(SequencerButtonsPanel):
- __label__ = "Filter"
- __idname__ = "SEQUENCER_PT_filter"
-
- def poll(self, context):
- if context.space_data.display_mode != 'SEQUENCER':
- return False
-
- strip = act_strip(context)
- if not strip:
- return False
-
- return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META')
-
- def draw(self, context):
- layout = self.layout
-
- strip = act_strip(context)
-
- split = layout.split()
-
- col = split.column()
- col.itemR(strip, "premultiply")
- col.itemR(strip, "convert_float")
- col.itemR(strip, "de_interlace")
- col.itemR(strip, "multiply_colors")
- col.itemR(strip, "strobe")
-
- col = split.column()
- col.itemL(text="Flip:")
- col.itemR(strip, "flip_x", text="X")
- col.itemR(strip, "flip_y", text="Y")
- col.itemR(strip, "reverse_frames", text="Backwards")
-
- layout.itemR(strip, "use_color_balance")
- if strip.color_balance: # TODO - need to add this somehow
- row = layout.row()
- row.active = strip.use_color_balance
- col = row.column()
- col.itemR(strip.color_balance, "lift")
- col.itemR(strip.color_balance, "inverse_lift")
- col = row.column()
- col.itemR(strip.color_balance, "gamma")
- col.itemR(strip.color_balance, "inverse_gamma")
- col = row.column()
- col.itemR(strip.color_balance, "gain")
- col.itemR(strip.color_balance, "inverse_gain")
-
-
-class SEQUENCER_PT_proxy(SequencerButtonsPanel):
- __label__ = "Proxy"
- __idname__ = "SEQUENCER_PT_proxy"
-
- def poll(self, context):
- if context.space_data.display_mode != 'SEQUENCER':
- return False
-
- strip = act_strip(context)
- if not strip:
- return False
-
- return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META')
-
- def draw_header(self, context):
- strip = act_strip(context)
-
- layout = self.layout
-
- layout.itemR(strip, "use_proxy", text="")
-
- def draw(self, context):
- strip = act_strip(context)
-
- layout = self.layout
-
- flow = layout.column_flow()
- flow.itemR(strip, "proxy_custom_directory")
- if strip.proxy: # TODO - need to add this somehow
- flow.itemR(strip.proxy, "directory")
- flow.itemR(strip.proxy, "file")
-
-
-class SEQUENCER_PT_view(SequencerButtonsPanel_Output):
- __label__ = "View Settings"
- __idname__ = "SEQUENCER_PT_view"
-
- def draw(self, context):
- st = context.space_data
-
- layout = self.layout
-
- flow = layout.column_flow()
- flow.itemR(st, "draw_overexposed") # text="Zebra"
- flow.itemR(st, "draw_safe_margin")
-
-
-bpy.types.register(SEQUENCER_HT_header) # header/menu classes
-bpy.types.register(SEQUENCER_MT_view)
-bpy.types.register(SEQUENCER_MT_select)
-bpy.types.register(SEQUENCER_MT_marker)
-bpy.types.register(SEQUENCER_MT_add)
-bpy.types.register(SEQUENCER_MT_add_effect)
-bpy.types.register(SEQUENCER_MT_strip)
-
-bpy.types.register(SEQUENCER_PT_edit) # sequencer panels
-bpy.types.register(SEQUENCER_PT_effect)
-bpy.types.register(SEQUENCER_PT_input)
-bpy.types.register(SEQUENCER_PT_filter)
-bpy.types.register(SEQUENCER_PT_proxy)
-
-bpy.types.register(SEQUENCER_PT_view) # view panels
-
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index f0796697670..1fb200b94a8 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -68,6 +68,9 @@ void make_local_action(struct bAction *act);
/* Some kind of bounding box operation on the action */
void calc_action_range(const struct bAction *act, float *start, float *end, int incl_hidden);
+/* Does action have any motion data at all? */
+short action_has_motion(const struct bAction *act);
+
/* Action Groups API ----------------- */
/* Make the given Action Group the active one */
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 9b8a2990fe5..5c77e3c2ae4 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -108,11 +108,17 @@ struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type);
void fcurve_copy_modifiers(ListBase *dst, ListBase *src);
void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm);
void fcurve_free_modifiers(struct FCurve *fcu);
-void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu);
void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm);
+short fcurve_has_suitable_modifier(struct FCurve *fcu, int mtype, short acttype);
+
+float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime);
+void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime);
+
+void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
+
/* ************** F-Curves API ******************** */
/* -------- Data Managemnt -------- */
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index 230096d7ea7..5200ca6d4d7 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -17,12 +17,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Joshua Leung (full recode)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -30,15 +30,48 @@
#ifndef BKE_NLA_H
#define BKE_NLA_H
-struct bActionStrip;
-struct ListBase;
-struct Object;
+struct AnimData;
+struct NlaStrip;
+struct NlaTrack;
+struct bAction;
+
+/* ----------------------------- */
+/* Data Management */
+
+void free_nlastrip(ListBase *strips, struct NlaStrip *strip);
+void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt);
+void free_nladata(ListBase *tracks);
+
+struct NlaStrip *copy_nlastrip(struct NlaStrip *strip);
+struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt);
+void copy_nladata(ListBase *dst, ListBase *src);
+
+struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev);
+struct NlaStrip *add_nlastrip(struct bAction *act);
+struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act);
+
+/* ----------------------------- */
+/* API */
+
+struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks);
+void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt);
+
+void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt);
+
+short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end);
+void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
+
+short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip);
+
+
+struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
+short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
+
+
+void BKE_nla_action_pushdown(struct AnimData *adt);
+
+short BKE_nla_tweakmode_enter(struct AnimData *adt);
+void BKE_nla_tweakmode_exit(struct AnimData *adt);
-void free_actionstrip (struct bActionStrip* strip);
-void free_nlastrips (struct ListBase *nlalist);
-void copy_nlastrips (struct ListBase *dst, struct ListBase *src);
-void copy_actionstrip (struct bActionStrip **dst, struct bActionStrip **src);
-void find_stridechannel(struct Object *ob, struct bActionStrip *strip);
-struct bActionStrip *convert_action_to_strip (struct Object *ob);
#endif
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
index 6584af085cd..0bed2c095e2 100644
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -128,6 +128,7 @@
#define IS_EQT(a, b, c) ((a > b)? (((a-b) <= c)? 1:0) : ((((b-a) <= c)? 1:0)))
#define IN_RANGE(a, b, c) ((b < c)? ((b<a && a<c)? 1:0) : ((c<a && a<b)? 1:0))
+#define IN_RANGE_INCL(a, b, c) ((b < c)? ((b<=a && a<=c)? 1:0) : ((c<=a && a<=b)? 1:0))
/* this weirdo pops up in two places ... */
#if !defined(WIN32) && !defined(__BeOS)
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index f7e15cef4c4..f88e249d38c 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -788,50 +788,45 @@ static bActionStrip *get_active_strip(Object *ob)
return NULL;
}
-/* non clipped mapping of strip */
-static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert)
-{
- float length, actlength, repeat, scale;
-
- if (strip->repeat == 0.0f) strip->repeat = 1.0f;
- repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat);
-
- if (strip->scale == 0.0f) strip->scale= 1.0f;
- scale = (float)fabs(strip->scale); /* scale must be positive (for now) */
-
- actlength = strip->actend-strip->actstart;
- if (actlength == 0.0f) actlength = 1.0f;
- length = repeat * scale * actlength;
-
- /* invert = convert action-strip time to global time */
- if (invert)
- return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start;
- else
- return repeat*actlength*(cframe - strip->start)/length + strip->actstart;
-}
-
/* if the conditions match, it converts current time to strip time */
+// TODO: change this adt
float get_action_frame(Object *ob, float cframe)
{
bActionStrip *strip= get_active_strip(ob);
- if(strip)
- return get_actionstrip_frame(strip, cframe, 0);
+ //if(strip)
+ // return get_actionstrip_frame(strip, cframe, 0);
return cframe;
}
/* inverted, strip time to current time */
+// TODO: change this to adt
float get_action_frame_inv(Object *ob, float cframe)
{
bActionStrip *strip= get_active_strip(ob);
- if(strip)
- return get_actionstrip_frame(strip, cframe, 1);
+ //if(strip)
+ // return get_actionstrip_frame(strip, cframe, 1);
return cframe;
}
-
+/* Check if the given action has any keyframes */
+short action_has_motion(const bAction *act)
+{
+ FCurve *fcu;
+
+ /* return on the first F-Curve that has some keyframes/samples defined */
+ if (act) {
+ for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+ if (fcu->totvert)
+ return 1;
+ }
+ }
+
+ /* nothing found */
+ return 0;
+}
/* Calculate the extents of given action */
void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden)
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 30dcb383ef6..2efb4f2b2d3 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -5,6 +5,8 @@
#include <stdio.h>
#include <string.h>
#include <stddef.h>
+#include <float.h>
+#include <math.h>
#include "MEM_guardedalloc.h"
@@ -15,6 +17,7 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_fcurve.h"
+#include "BKE_nla.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_utildefines.h"
@@ -115,7 +118,13 @@ void BKE_free_animdata (ID *id)
/* unlink action (don't free, as it's in its own list) */
if (adt->action)
adt->action->id.us--;
+ /* same goes for the temporarily displaced action */
+ if (adt->tmpact)
+ adt->tmpact->id.us--;
+ /* free nla data */
+ free_nladata(&adt->nla_tracks);
+
/* free drivers - stored as a list of F-Curves */
free_fcurves(&adt->drivers);
@@ -145,9 +154,10 @@ AnimData *BKE_copy_animdata (AnimData *adt)
// XXX review this... it might not be optimal behaviour yet...
//id_us_plus((ID *)dadt->action);
dadt->action= copy_action(adt->action);
+ dadt->tmpact= copy_action(adt->tmpact);
/* duplicate NLA data */
- // XXX todo...
+ copy_nladata(&dadt->nla_tracks, &adt->nla_tracks);
/* duplicate drivers (F-Curves) */
copy_fcurves(&dadt->drivers, &adt->drivers);
@@ -544,19 +554,24 @@ typedef struct NlaEvalStrip {
struct NlaEvalStrip *next, *prev;
NlaTrack *track; /* track that this strip belongs to */
- NlaStrip *strip; /* strip that's being used */
- NlaStrip *sblend; /* strip that's being blended towards (if applicable) */
+ NlaStrip *strip; /* strip that's being used */
short track_index; /* the index of the track within the list */
short strip_mode; /* which end of the strip are we looking at */
+
+ float strip_time; /* time at which which strip is being evaluated */
} NlaEvalStrip;
-/* bNlaEvalStrip->strip_mode */
+/* NlaEvalStrip->strip_mode */
enum {
+ /* standard evaluation */
NES_TIME_BEFORE = -1,
NES_TIME_WITHIN,
NES_TIME_AFTER,
- NES_TIME_AFTER_BLEND
+
+ /* transition-strip evaluations */
+ NES_TIME_TRANSITION_START,
+ NES_TIME_TRANSITION_END,
} eNlaEvalStrip_StripMode;
@@ -565,8 +580,9 @@ enum {
typedef struct NlaEvalChannel {
struct NlaEvalChannel *next, *prev;
- char *path; /* ready-to-use path (i.e. remapped already) */
- int array_index; /* if applicable... */
+ PointerRNA ptr; /* pointer to struct containing property to use */
+ PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */
+ int index; /* array index (where applicable) */
float value; /* value of this channel */
} NlaEvalChannel;
@@ -574,117 +590,548 @@ typedef struct NlaEvalChannel {
/* ---------------------- */
-/* evaluate the F-Curves controlling settings for the NLA-strips (currently, not relinkable) */
-static void nlastrip_evaluate_fcurves (NlaStrip *strip, float ctime)
+/* non clipped mapping for strip-time <-> global time (for Action-Clips)
+ * invert = convert action-strip time to global time
+ */
+static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert)
{
- //PointerRNA actstrip_ptr;
- //FCurve *fcu;
+ float length, actlength, repeat, scale;
+
+ /* get number of repeats */
+ if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f;
+ repeat = strip->repeat;
+
+ /* scaling */
+ if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f;
+ scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */
- /* create RNA-pointer needed to set values */
- //RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &actstrip_ptr);
+ /* length of referenced action */
+ actlength = strip->actend - strip->actstart;
+ if (IS_EQ(actlength, 0.0f)) actlength = 1.0f;
- /* execute these settings as per normal */
- //animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime);
+ /* length of strip */
+ length= actlength * scale * repeat;
+ if (IS_EQ(length, 0.0f)) length= strip->end - strip->start;
+
+ /* reversed = play strip backwards */
+ if (strip->flag & NLASTRIP_FLAG_REVERSE) {
+ /* invert = convert action-strip time to global time */
+ if (invert)
+ return length*(strip->actend - cframe)/(repeat*actlength) + strip->start;
+ else
+ return strip->actend - repeat*actlength*(cframe - strip->start)/length;
+ }
+ else {
+ /* invert = convert action-strip time to global time */
+ if (invert)
+ return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start;
+ else
+ return repeat*actlength*(cframe - strip->start)/length + strip->actstart;
+ }
+}
+
+/* non clipped mapping for strip-time <-> global time (for Transitions)
+ * invert = convert action-strip time to global time
+ */
+static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert)
+{
+ float length;
+
+ /* length of strip */
+ length= strip->end - strip->start;
+
+ /* reversed = play strip backwards */
+ if (strip->flag & NLASTRIP_FLAG_REVERSE) {
+ /* invert = convert within-strip-time to global time */
+ if (invert)
+ return strip->end - (length * cframe);
+ else
+ return (strip->end - cframe) / length;
+ }
+ else {
+ /* invert = convert within-strip-time to global time */
+ if (invert)
+ return (length * cframe) + strip->start;
+ else
+ return (cframe - strip->start) / length;
+ }
}
+/* non clipped mapping for strip-time <-> global time
+ * invert = convert action-strip time to global time
+ */
+static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert)
+{
+ switch (strip->type) {
+ case NLASTRIP_TYPE_TRANSITION: /* transition */
+ return nlastrip_get_frame_transition(strip, cframe, invert);
+
+ case NLASTRIP_TYPE_CLIP: /* action-clip (default) */
+ default:
+ return nlastrip_get_frame_actionclip(strip, cframe, invert);
+ }
+}
+
+/* calculate influence of strip based for given frame based on blendin/out values */
+static float nlastrip_get_influence (NlaStrip *strip, float cframe)
+{
+ /* sanity checks - normalise the blendin/out values? */
+ strip->blendin= (float)fabs(strip->blendin);
+ strip->blendout= (float)fabs(strip->blendout);
+
+ /* result depends on where frame is in respect to blendin/out values */
+ if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) {
+ /* there is some blend-in */
+ return (float)fabs(cframe - strip->start) / (strip->blendin);
+ }
+ else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) {
+ /* there is some blend-out */
+ return (float)fabs(strip->end - cframe) / (strip->blendout);
+ }
+ else {
+ /* in the middle of the strip, we should be full strength */
+ return 1.0f;
+ }
+}
-/* gets the strip active at the current time for a track */
+/* evaluate the evaluation time and influence for the strip, storing the results in the strip */
+void nlastrip_evaluate_controls (NlaStrip *strip, float ctime)
+{
+ /* firstly, analytically generate values for influence and time (if applicable) */
+ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0)
+ strip->strip_time= nlastrip_get_frame(strip, ctime, 0);
+ if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0)
+ strip->influence= nlastrip_get_influence(strip, ctime);
+
+ /* now strip's evaluate F-Curves for these settings (if applicable) */
+ if (strip->fcurves.first) {
+ PointerRNA strip_ptr;
+
+ /* create RNA-pointer needed to set values */
+ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
+
+ /* execute these settings as per normal */
+ animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime);
+ }
+}
+
+
+/* gets the strip active at the current time for a track for evaluation purposes */
static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime)
{
- NlaStrip *strip, *astrip=NULL, *bstrip=NULL;
+ NlaStrip *strip, *estrip=NULL;
NlaEvalStrip *nes;
short side= 0;
- /* skip if track is muted */
- if (nlt->flag & NLATRACK_MUTED)
- return;
-
/* loop over strips, checking if they fall within the range */
for (strip= nlt->strips.first; strip; strip= strip->next) {
- /* only consider if:
- * - current time occurs within strip's extents
- * - current time occurs before strip (if it is the first)
- * - current time occurs after strip (if hold is on)
- * - current time occurs between strips (1st of those isn't holding) - blend!
- */
- if (IN_RANGE(ctime, strip->start, strip->end)) {
- astrip= strip;
+ /* check if current time occurs within this strip */
+ if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
+ /* this strip is active, so try to use it */
+ estrip= strip;
side= NES_TIME_WITHIN;
break;
}
- else if (ctime < strip->start) {
+
+ /* if time occurred before current strip... */
+ if (ctime < strip->start) {
if (strip == nlt->strips.first) {
- astrip= strip;
+ /* before first strip - only try to use it if it extends backwards in time too */
+ if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
+ estrip= strip;
+
+ /* side is 'before' regardless of whether there's a useful strip */
side= NES_TIME_BEFORE;
- break;
}
else {
- astrip= strip->prev;
+ /* before next strip - previous strip has ended, but next hasn't begun,
+ * so blending mode depends on whether strip is being held or not...
+ * - only occurs when no transition strip added, otherwise the transition would have
+ * been picked up above...
+ */
+ strip= strip->prev;
- if (astrip->flag & NLASTRIP_HOLDLASTFRAME) {
- side= NES_TIME_AFTER;
- break;
- }
- else {
- bstrip= strip;
- side= NES_TIME_AFTER_BLEND;
- break;
- }
+ if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
+ estrip= strip;
+ side= NES_TIME_AFTER;
+ }
+ break;
+ }
+
+ /* if time occurred after current strip... */
+ if (ctime > strip->end) {
+ /* only if this is the last strip should we do anything, and only if that is being held */
+ if (strip == nlt->strips.last) {
+ if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
+ estrip= strip;
+
+ side= NES_TIME_AFTER;
+ break;
}
+
+ /* otherwise, skip... as the 'before' case will catch it more elegantly! */
}
}
- /* check if strip has been found (and whether it has data worth considering) */
- if (ELEM(NULL, astrip, astrip->act))
- return;
- if (astrip->flag & NLASTRIP_MUTE)
+ /* check if a valid strip was found
+ * - must not be muted (i.e. will have contribution
+ */
+ if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED))
return;
-
- /* check if blending between strips */
- if (side == NES_TIME_AFTER_BLEND) {
- /* blending between strips... so calculate influence+act_time of both */
- nlastrip_evaluate_fcurves(astrip, ctime);
- nlastrip_evaluate_fcurves(bstrip, ctime);
- if ((astrip->influence <= 0.0f) && (bstrip->influence <= 0.0f))
- return;
+ /* if ctime was not within the boundaries of the strip, clamp! */
+ switch (side) {
+ case NES_TIME_BEFORE: /* extend first frame only */
+ ctime= estrip->start;
+ break;
+ case NES_TIME_AFTER: /* extend last frame only */
+ ctime= estrip->end;
+ break;
}
- else {
- /* calculate/set the influence+act_time of this strip - don't consider if 0 influence */
- nlastrip_evaluate_fcurves(astrip, ctime);
+
+ /* evaluate strip's evaluation controls
+ * - skip if no influence (i.e. same effect as muting the strip)
+ * - negative influence is not supported yet... how would that be defined?
+ */
+ // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on...
+ nlastrip_evaluate_controls(estrip, ctime);
+ if (estrip->influence <= 0.0f) // XXX is it useful to invert the strip?
+ return;
- if (astrip->influence <= 0.0f)
- return;
+ /* check if strip has valid data to evaluate,
+ * and/or perform any additional type-specific actions
+ */
+ switch (estrip->type) {
+ case NLASTRIP_TYPE_CLIP:
+ /* clip must have some action to evaluate */
+ if (estrip->act == NULL)
+ return;
+ break;
+ case NLASTRIP_TYPE_TRANSITION:
+ /* there must be strips to transition from and to (i.e. prev and next required) */
+ if (ELEM(NULL, estrip->prev, estrip->next))
+ return;
+
+ /* evaluate controls for the relevant extents of the bordering strips... */
+ nlastrip_evaluate_controls(estrip->prev, estrip->start);
+ nlastrip_evaluate_controls(estrip->next, estrip->end);
+ break;
}
-
- /* allocate new eval-strip for this strip + add to stack */
+ /* add to list of strips we need to evaluate */
nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip");
nes->track= nlt;
- nes->strip= astrip;
- nes->sblend= bstrip;
- nes->track_index= index;
+ nes->strip= estrip;
nes->strip_mode= side;
+ nes->track_index= index;
+ nes->strip_time= estrip->strip_time;
BLI_addtail(list, nes);
}
/* ---------------------- */
+/* find an NlaEvalChannel that matches the given criteria
+ * - ptr and prop are the RNA data to find a match for
+ */
+static NlaEvalChannel *nlaevalchan_find_match (ListBase *channels, PointerRNA *ptr, PropertyRNA *prop, int array_index)
+{
+ NlaEvalChannel *nec;
+
+ /* sanity check */
+ if (channels == NULL)
+ return NULL;
+
+ /* loop through existing channels, checking for a channel which affects the same property */
+ for (nec= channels->first; nec; nec= nec->next) {
+ /* - comparing the PointerRNA's is done by comparing the pointers
+ * to the actual struct the property resides in, since that all the
+ * other data stored in PointerRNA cannot allow us to definitively
+ * identify the data
+ */
+ if ((nec->ptr.data == ptr->data) && (nec->prop == prop) && (nec->index == array_index))
+ return nec;
+ }
+
+ /* not found */
+ return NULL;
+}
+
+/* verify that an appropriate NlaEvalChannel for this F-Curve exists */
+static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan)
+{
+ NlaEvalChannel *nec;
+ NlaStrip *strip= nes->strip;
+ PropertyRNA *prop;
+ PointerRNA new_ptr;
+ char *path = NULL;
+ short free_path=0;
+
+ /* sanity checks */
+ if (channels == NULL)
+ return NULL;
+
+ /* get RNA pointer+property info from F-Curve for more convenient handling */
+ /* get path, remapped as appropriate to work in its new environment */
+ free_path= animsys_remap_path(strip->remap, fcu->rna_path, &path);
+
+ /* a valid property must be available, and it must be animateable */
+ if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) {
+ if (G.f & G_DEBUG) printf("NLA Strip Eval: Cannot resolve path \n");
+ return NULL;
+ }
+ /* only ok if animateable */
+ else if (RNA_property_animateable(&new_ptr, prop) == 0) {
+ if (G.f & G_DEBUG) printf("NLA Strip Eval: Property not animateable \n");
+ return NULL;
+ }
+
+ /* try to find a match */
+ nec= nlaevalchan_find_match(channels, &new_ptr, prop, fcu->array_index);
+
+ /* allocate a new struct for this if none found */
+ if (nec == NULL) {
+ nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel");
+ *newChan= 1;
+ BLI_addtail(channels, nec);
+
+ nec->ptr= new_ptr;
+ nec->prop= prop;
+ nec->index= fcu->array_index;
+ }
+ else
+ *newChan= 0;
+
+ /* we can now return */
+ return nec;
+}
+
+/* accumulate (i.e. blend) the given value on to the channel it affects */
+static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value)
+{
+ NlaStrip *strip= nes->strip;
+ short blendmode= strip->blendmode;
+ float inf= strip->influence;
+
+ /* if channel is new, just store value regardless of blending factors, etc. */
+ if (newChan) {
+ nec->value= value;
+ return;
+ }
+
+ /* if this is being performed as part of transition evaluation, incorporate
+ * an additional weighting factor for the influence
+ */
+ if (nes->strip_mode == NES_TIME_TRANSITION_END)
+ inf *= nes->strip_time;
+
+ /* premultiply the value by the weighting factor */
+ if (IS_EQ(inf, 0)) return;
+ value *= inf;
+
+ /* perform blending */
+ switch (blendmode) {
+ case NLASTRIP_MODE_ADD:
+ /* simply add the scaled value on to the stack */
+ nec->value += value;
+ break;
+
+ case NLASTRIP_MODE_SUBTRACT:
+ /* simply subtract the scaled value from the stack */
+ nec->value -= value;
+ break;
+
+ case NLASTRIP_MODE_MULTIPLY:
+ /* multiply the scaled value with the stack */
+ nec->value *= value;
+ break;
+
+ case NLASTRIP_MODE_BLEND:
+ default: // TODO: do we really want to blend by default? it seems more uses might prefer add...
+ /* do linear interpolation
+ * - the influence of the accumulated data (elsewhere, that is called dstweight)
+ * is 1 - influence, since the strip's influence is srcweight
+ */
+ nec->value= nec->value * (1.0f - inf) + value;
+ break;
+ }
+}
+
+/* ---------------------- */
+
+/* evaluate action-clip strip */
+static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes)
+{
+ NlaStrip *strip= nes->strip;
+ FCurve *fcu;
+ float evaltime;
+
+ /* evaluate strip's modifiers which modify time to evaluate the base curves at */
+ evaltime= evaluate_time_fmodifiers(&strip->modifiers, NULL, 0.0f, strip->strip_time);
+
+ /* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */
+ for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) {
+ NlaEvalChannel *nec;
+ float value = 0.0f;
+ short newChan = -1;
+
+ /* check if this curve should be skipped */
+ if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED))
+ continue;
+
+ /* evaluate the F-Curve's value for the time given in the strip
+ * NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this
+ */
+ value= evaluate_fcurve(fcu, evaltime);
+
+ /* apply strip's F-Curve Modifiers on this value
+ * NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval)
+ */
+ evaluate_value_fmodifiers(&strip->modifiers, fcu, &value, strip->strip_time);
+
+
+ /* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s)
+ * stored in this channel if it has been used already
+ */
+ nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan);
+ if (nec)
+ nlaevalchan_accumulate(nec, nes, newChan, value);
+ }
+}
+
+/* evaluate transition strip */
+static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes)
+{
+ ListBase tmp_channels = {NULL, NULL};
+ NlaEvalChannel *nec, *necn, *necd;
+ NlaEvalStrip tmp_nes;
+ NlaStrip *s1, *s2;
+
+ /* get the two strips to operate on
+ * - we use the endpoints of the strips directly flanking our strip
+ * using these as the endpoints of the transition (destination and source)
+ * - these should have already been determined to be valid...
+ * - if this strip is being played in reverse, we need to swap these endpoints
+ * otherwise they will be interpolated wrong
+ */
+ if (nes->strip->flag & NLASTRIP_FLAG_REVERSE) {
+ s1= nes->strip->next;
+ s2= nes->strip->prev;
+ }
+ else {
+ s1= nes->strip->prev;
+ s2= nes->strip->next;
+ }
+
+ /* prepare template for 'evaluation strip'
+ * - based on the transition strip's evaluation strip data
+ * - strip_mode is NES_TIME_TRANSITION_* based on which endpoint
+ * - strip_time is the 'normalised' (i.e. in-strip) time for evaluation,
+ * which doubles up as an additional weighting factor for the strip influences
+ * which allows us to appear to be 'interpolating' between the two extremes
+ */
+ tmp_nes= *nes;
+
+ /* evaluate these strips into a temp-buffer (tmp_channels) */
+ /* first strip */
+ tmp_nes.strip_mode= NES_TIME_TRANSITION_START;
+ tmp_nes.strip= s1;
+ nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes);
+
+ /* second strip */
+ tmp_nes.strip_mode= NES_TIME_TRANSITION_END;
+ tmp_nes.strip= s2;
+ nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes);
+
+
+ /* optimise - abort if no channels */
+ if (tmp_channels.first == NULL)
+ return;
+
+
+ /* accumulate results in tmp_channels buffer to the accumulation buffer */
+ for (nec= tmp_channels.first; nec; nec= necn) {
+ /* get pointer to next channel in case we remove the current channel from the temp-buffer */
+ necn= nec->next;
+
+ /* try to find an existing matching channel for this setting in the accumulation buffer */
+ necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index);
+
+ /* if there was a matching channel already in the buffer, accumulate to it,
+ * otherwise, add the current channel to the buffer for efficiency
+ */
+ if (necd)
+ nlaevalchan_accumulate(necd, nes, 0, nec->value);
+ else {
+ BLI_remlink(&tmp_channels, nec);
+ BLI_addtail(channels, nec);
+ }
+ }
+
+ /* free temp-channels that haven't been assimilated into the buffer */
+ BLI_freelistN(&tmp_channels);
+}
+
/* evaluates the given evaluation strip */
-// FIXME: will we need the evaluation cache table set up to blend stuff in?
-// TODO: only evaluate here, but flush in one go using the accumulated channels at end...
-static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime)
+static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes)
{
- // 1. (in old code) was to extract 'IPO-channels' from actions
- // 2. blend between the 'accumulated' data, and the new data
+ /* actions to take depend on the type of strip */
+ switch (nes->strip->type) {
+ case NLASTRIP_TYPE_CLIP: /* action-clip */
+ nlastrip_evaluate_actionclip(ptr, channels, nes);
+ break;
+ case NLASTRIP_TYPE_TRANSITION: /* transition */
+ nlastrip_evaluate_transition(ptr, channels, nes);
+ break;
+ }
}
/* write the accumulated settings to */
-static void nladata_flush_channels (PointerRNA *ptr, ListBase *channels)
+static void nladata_flush_channels (ListBase *channels)
{
+ NlaEvalChannel *nec;
+
+ /* sanity checks */
+ if (channels == NULL)
+ return;
+ /* for each channel with accumulated values, write its value on the property it affects */
+ for (nec= channels->first; nec; nec= nec->next) {
+ PointerRNA *ptr= &nec->ptr;
+ PropertyRNA *prop= nec->prop;
+ int array_index= nec->index;
+ float value= nec->value;
+
+ /* write values - see animsys_write_rna_setting() to sync the code */
+ switch (RNA_property_type(prop))
+ {
+ case PROP_BOOLEAN:
+ if (RNA_property_array_length(prop))
+ RNA_property_boolean_set_index(ptr, prop, array_index, (int)value);
+ else
+ RNA_property_boolean_set(ptr, prop, (int)value);
+ break;
+ case PROP_INT:
+ if (RNA_property_array_length(prop))
+ RNA_property_int_set_index(ptr, prop, array_index, (int)value);
+ else
+ RNA_property_int_set(ptr, prop, (int)value);
+ break;
+ case PROP_FLOAT:
+ if (RNA_property_array_length(prop))
+ RNA_property_float_set_index(ptr, prop, array_index, value);
+ else
+ RNA_property_float_set(ptr, prop, value);
+ break;
+ case PROP_ENUM:
+ RNA_property_enum_set(ptr, prop, (int)value);
+ break;
+ default:
+ // can't do anything with other types of property....
+ break;
+ }
+ }
}
/* ---------------------- */
@@ -703,8 +1150,21 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
NlaEvalStrip *nes;
/* 1. get the stack of strips to evaluate at current time (influence calculated here) */
- for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++)
+ for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) {
+ /* if tweaking is on and this strip is the tweaking track, stop on this one */
+ if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED))
+ break;
+
+ /* skip if we're only considering a track tagged 'solo' */
+ if ((adt->flag & ADT_NLA_SOLO_TRACK) && (nlt->flag & NLATRACK_SOLO)==0)
+ continue;
+ /* skip if track is muted */
+ if (nlt->flag & NLATRACK_MUTED)
+ continue;
+
+ /* otherwise, get strip to evaluate for this channel */
nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime);
+ }
/* only continue if there are strips to evaluate */
if (estrips.first == NULL)
@@ -713,10 +1173,10 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
/* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */
for (nes= estrips.first; nes; nes= nes->next)
- nlastrip_ctime_evaluate(&echannels, nes, ctime);
+ nlastrip_evaluate(ptr, &echannels, nes);
/* 3. flush effects of accumulating channels in NLA to the actual data they affect */
- nladata_flush_channels(ptr, &echannels);
+ nladata_flush_channels(&echannels);
/* 4. free temporary evaluation data */
BLI_freelistN(&estrips);
@@ -798,17 +1258,23 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re
* - NLA before Active Action, as Active Action behaves as 'tweaking track'
* that overrides 'rough' work in NLA
*/
+ // TODO: need to double check that this all works correctly
if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM))
{
/* evaluate NLA data */
if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF))
{
+ /* evaluate NLA-stack */
animsys_evaluate_nla(&id_ptr, adt, ctime);
+
+ /* evaluate 'active' Action (may be tweaking track) on top of results of NLA-evaluation
+ * - only do this if we're not exclusively evaluating the 'solo' NLA-track
+ */
+ if ((adt->action) && !(adt->flag & ADT_NLA_SOLO_TRACK))
+ animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
}
-
- /* evaluate Action data */
- // FIXME: what if the solo track was not tweaking one, then nla-solo should be checked too?
- if (adt->action)
+ /* evaluate Active Action only */
+ else if (adt->action)
animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
/* reset tag */
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index ad8115ba9aa..856930e5a44 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1410,6 +1410,18 @@ static void fcm_generator_verify (FModifier *fcm)
}
}
+/* Unary 'normalised sine' function
+ * y = sin(PI + x) / (PI * x),
+ * except for x = 0 when y = 1.
+ */
+static double sinc (double x)
+{
+ if (fabs(x) < 0.0001)
+ return 1.0;
+ else
+ return sin(M_PI * x) / (M_PI * x);
+}
+
static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
@@ -1490,6 +1502,9 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
case FCM_GENERATOR_FN_COS: /* cosine wave */
fn= cos;
break;
+ case FCM_GENERATOR_FN_SINC: /* normalised sine wave */
+ fn= sinc;
+ break;
/* validation required */
case FCM_GENERATOR_FN_TAN: /* tangent wave */
@@ -1527,7 +1542,7 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
}
}
break;
-
+
default:
printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type);
}
@@ -2190,34 +2205,6 @@ void fcurve_free_modifiers (FCurve *fcu)
}
}
-/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
- * by start and end (inclusive).
- */
-void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
-{
- ChannelDriver *driver;
-
- /* sanity checks */
- // TODO: make these tests report errors using reports not printf's
- if ELEM(NULL, fcu, fcu->modifiers.first) {
- printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
- return;
- }
-
- /* temporarily, disable driver while we sample, so that they don't influence the outcome */
- driver= fcu->driver;
- fcu->driver= NULL;
-
- /* bake the modifiers, by sampling the curve at each frame */
- fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
-
- /* free the modifiers now */
- fcurve_free_modifiers(fcu);
-
- /* restore driver */
- fcu->driver= driver;
-}
-
/* Find the active F-Curve Modifier */
FModifier *fcurve_find_active_modifier (FCurve *fcu)
{
@@ -2255,6 +2242,134 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm)
fcm->flag |= FMODIFIER_FLAG_ACTIVE;
}
+/* Do we have any modifiers which match certain criteria
+ * - mtype - type of modifier (if 0, doesn't matter)
+ * - acttype - type of action to perform (if -1, doesn't matter)
+ */
+short fcurve_has_suitable_modifier (FCurve *fcu, int mtype, short acttype)
+{
+ FModifier *fcm;
+
+ /* if there are no specific filtering criteria, just skip */
+ if ((mtype == 0) && (acttype == 0))
+ return (fcu && fcu->modifiers.first);
+
+ /* sanity checks */
+ if ELEM(NULL, fcu, fcu->modifiers.first)
+ return 0;
+
+ /* find the first mdifier fitting these criteria */
+ for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+ short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */
+
+ /* check if applicable ones are fullfilled */
+ if (mtype)
+ mOk= (fcm->type == mtype);
+ if (acttype > -1)
+ aOk= (fmi->acttype == acttype);
+
+ /* if both are ok, we've found a hit */
+ if (mOk && aOk)
+ return 1;
+ }
+
+ /* no matches */
+ return 0;
+}
+
+/* Evaluation API --------------------------- */
+
+/* evaluate time modifications imposed by some F-Curve Modifiers
+ * - this step acts as an optimisation to prevent the F-Curve stack being evaluated
+ * several times by modifiers requesting the time be modified, as the final result
+ * would have required using the modified time
+ * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be
+ * working on the 'global' result of the modified curve, not some localised segment,
+ * so nevaltime gets set to whatever the last time-modifying modifier likes...
+ * - we start from the end of the stack, as only the last one matters for now
+ */
+float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime)
+{
+ FModifier *fcm;
+ float m_evaltime= evaltime;
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, modifiers->first)
+ return evaltime;
+
+ /* find the first modifier from end of stack that modifies time, and calculate the time the modifier
+ * would calculate time at
+ */
+ for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* only evaluate if there's a callback for this */
+ // TODO: implement the 'influence' control feature...
+ if (fmi && fmi->evaluate_modifier_time) {
+ if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
+ m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
+ break;
+ }
+ }
+
+ /* return the modified evaltime */
+ return m_evaltime;
+}
+
+/* Evalautes the given set of F-Curve Modifiers using the given data
+ * Should only be called after evaluate_time_fmodifiers() has been called...
+ */
+void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime)
+{
+ FModifier *fcm;
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, modifiers->first)
+ return;
+
+ /* evaluate modifiers */
+ for (fcm= modifiers->first; fcm; fcm= fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* only evaluate if there's a callback for this */
+ // TODO: implement the 'influence' control feature...
+ if (fmi && fmi->evaluate_modifier) {
+ if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
+ fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime);
+ }
+ }
+}
+
+
+/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
+ * by start and end (inclusive).
+ */
+void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
+{
+ ChannelDriver *driver;
+
+ /* sanity checks */
+ // TODO: make these tests report errors using reports not printf's
+ if ELEM(NULL, fcu, fcu->modifiers.first) {
+ printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
+ return;
+ }
+
+ /* temporarily, disable driver while we sample, so that they don't influence the outcome */
+ driver= fcu->driver;
+ fcu->driver= NULL;
+
+ /* bake the modifiers, by sampling the curve at each frame */
+ fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
+
+ /* free the modifiers now */
+ fcurve_free_modifiers(fcu);
+
+ /* restore driver */
+ fcu->driver= driver;
+}
+
/* ***************************** F-Curve - Evaluation ********************************* */
/* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime")
@@ -2262,7 +2377,6 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm)
*/
float evaluate_fcurve (FCurve *fcu, float evaltime)
{
- FModifier *fcm;
float cvalue= 0.0f;
float devaltime;
@@ -2275,28 +2389,8 @@ float evaluate_fcurve (FCurve *fcu, float evaltime)
evaltime= cvalue= evaluate_driver(fcu->driver, evaltime);
}
- /* evaluate time modifications imposed by some F-Curve Modifiers
- * - this step acts as an optimisation to prevent the F-Curve stack being evaluated
- * several times by modifiers requesting the time be modified, as the final result
- * would have required using the modified time
- * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be
- * working on the 'global' result of the modified curve, not some localised segment,
- * so nevaltime gets set to whatever the last time-modifying modifier likes...
- * - we start from the end of the stack, as only the last one matters for now
- */
- devaltime= evaltime;
-
- for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* only evaluate if there's a callback for this */
- // TODO: implement the 'influence' control feature...
- if (fmi && fmi->evaluate_modifier_time) {
- if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
- devaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
- break;
- }
- }
+ /* evaluate modifiers which modify time to evaluate the base curve at */
+ devaltime= evaluate_time_fmodifiers(&fcu->modifiers, fcu, cvalue, evaltime);
/* evaluate curve-data
* - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying
@@ -2308,16 +2402,7 @@ float evaluate_fcurve (FCurve *fcu, float evaltime)
cvalue= fcurve_eval_samples(fcu, fcu->fpt, devaltime);
/* evaluate modifiers */
- for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* only evaluate if there's a callback for this */
- // TODO: implement the 'influence' control feature...
- if (fmi && fmi->evaluate_modifier) {
- if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
- fmi->evaluate_modifier(fcu, fcm, &cvalue, evaltime);
- }
- }
+ evaluate_value_fmodifiers(&fcu->modifiers, fcu, &cvalue, evaltime);
/* if curve can only have integral values, perform truncation (i.e. drop the decimal part)
* here so that the curve can be sampled correctly
@@ -2330,10 +2415,16 @@ float evaluate_fcurve (FCurve *fcu, float evaltime)
}
/* Calculate the value of the given F-Curve at the given frame, and set its curval */
-// TODO: will this be necessary?
void calculate_fcurve (FCurve *fcu, float ctime)
{
- /* calculate and set curval (evaluates driver too) */
- fcu->curval= evaluate_fcurve(fcu, ctime);
+ /* only calculate + set curval (overriding the existing value) if curve has
+ * any data which warrants this...
+ */
+ if ( (fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) ||
+ fcurve_has_suitable_modifier(fcu, 0, FMI_TYPE_GENERATE_CURVE) )
+ {
+ /* calculate and set curval (evaluates driver too if necessary) */
+ fcu->curval= evaluate_fcurve(fcu, ctime);
+ }
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index dc2bf26759f..0684d943754 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -17,171 +17,722 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Joshua Leung (full recode)
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "DNA_space_types.h"
-#include "DNA_nla_types.h"
+#include "DNA_anim_types.h"
#include "DNA_action_types.h"
-#include "DNA_ID.h"
-#include "DNA_ipo_types.h"
-#include "DNA_object_types.h"
-#include "BKE_nla.h"
+#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_fcurve.h"
+#include "BKE_nla.h"
#include "BKE_blender.h"
#include "BKE_library.h"
-#include "BKE_object.h" /* for convert_action_to_strip(ob) */
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-/* NOTE: in group.c the strips get copied for group-nla override, this assumes
- that strips are one single block, without additional data to be copied */
-void copy_actionstrip (bActionStrip **dst, bActionStrip **src){
- bActionStrip *dstrip;
- bActionStrip *sstrip = *src;
+/* *************************************************** */
+/* Data Management */
+
+/* Freeing ------------------------------------------- */
- if (!*src){
- *dst=NULL;
+/* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
+ * and the strip itself.
+ */
+// TODO: with things like transitions, should these get freed too? Maybe better as a UI tool
+void free_nlastrip (ListBase *strips, NlaStrip *strip)
+{
+ FModifier *fcm, *fmn;
+
+ /* sanity checks */
+ if (strip == NULL)
return;
+
+ /* remove reference to action */
+ if (strip->act)
+ strip->act->id.us--;
+
+ /* free remapping info */
+ //if (strip->remap)
+ // BKE_animremap_free();
+
+ /* free own F-Curves */
+ free_fcurves(&strip->fcurves);
+
+ /* free F-Modifiers */
+ for (fcm= strip->modifiers.first; fcm; fcm= fmn) {
+ fmn= fcm->next;
+
+ BLI_remlink(&strip->modifiers, fcm);
+ fcurve_remove_modifier(NULL, fcm);
}
+
+ /* free the strip itself */
+ if (strips)
+ BLI_freelinkN(strips, strip);
+ else
+ MEM_freeN(strip);
+}
- *dst = MEM_dupallocN(sstrip);
+/* Remove the given NLA track from the set of NLA tracks, free the track's data,
+ * and the track itself.
+ */
+void free_nlatrack (ListBase *tracks, NlaTrack *nlt)
+{
+ NlaStrip *strip, *stripn;
+
+ /* sanity checks */
+ if (nlt == NULL)
+ return;
+
+ /* free strips */
+ for (strip= nlt->strips.first; strip; strip= stripn) {
+ stripn= strip->next;
+ free_nlastrip(&nlt->strips, strip);
+ }
+
+ /* free NLA track itself now */
+ if (tracks)
+ BLI_freelinkN(tracks, nlt);
+ else
+ MEM_freeN(nlt);
+}
- dstrip = *dst;
- if (dstrip->act)
- dstrip->act->id.us++;
+/* Free the elements of type NLA Tracks provided in the given list, but do not free
+ * the list itself since that is not free-standing
+ */
+void free_nladata (ListBase *tracks)
+{
+ NlaTrack *nlt, *nltn;
+
+ /* sanity checks */
+ if ELEM(NULL, tracks, tracks->first)
+ return;
+
+ /* free tracks one by one */
+ for (nlt= tracks->first; nlt; nlt= nltn) {
+ nltn= nlt->next;
+ free_nlatrack(tracks, nlt);
+ }
+
+ /* clear the list's pointers to be safe */
+ tracks->first= tracks->last= NULL;
+}
- if (dstrip->ipo)
- dstrip->ipo->id.us++;
+/* Copying ------------------------------------------- */
+
+/* Copy NLA strip */
+NlaStrip *copy_nlastrip (NlaStrip *strip)
+{
+ NlaStrip *strip_d;
+
+ /* sanity check */
+ if (strip == NULL)
+ return NULL;
+
+ /* make a copy */
+ strip_d= MEM_dupallocN(strip);
+ strip_d->next= strip_d->prev= NULL;
- if (dstrip->modifiers.first) {
- BLI_duplicatelist (&dstrip->modifiers, &sstrip->modifiers);
+ /* increase user-count of action */
+ if (strip_d->act)
+ strip_d->act->id.us++;
+
+ /* copy F-Curves and modifiers */
+ copy_fcurves(&strip_d->fcurves, &strip->fcurves);
+ fcurve_copy_modifiers(&strip_d->modifiers, &strip->modifiers);
+
+ /* return the strip */
+ return strip_d;
+}
+
+/* Copy NLA Track */
+NlaTrack *copy_nlatrack (NlaTrack *nlt)
+{
+ NlaStrip *strip, *strip_d;
+ NlaTrack *nlt_d;
+
+ /* sanity check */
+ if (nlt == NULL)
+ return NULL;
+
+ /* make a copy */
+ nlt_d= MEM_dupallocN(nlt);
+ nlt_d->next= nlt_d->prev= NULL;
+
+ /* make a copy of all the strips, one at a time */
+ nlt_d->strips.first= nlt_d->strips.last= NULL;
+
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ strip_d= copy_nlastrip(strip);
+ BLI_addtail(&nlt_d->strips, strip_d);
}
+ /* return the copy */
+ return nlt_d;
}
-void copy_nlastrips (ListBase *dst, ListBase *src)
+/* Copy all NLA data */
+void copy_nladata (ListBase *dst, ListBase *src)
{
- bActionStrip *strip;
+ NlaTrack *nlt, *nlt_d;
+
+ /* sanity checks */
+ if ELEM(NULL, dst, src)
+ return;
+
+ /* copy each NLA-track, one at a time */
+ for (nlt= src->first; nlt; nlt= nlt->next) {
+ /* make a copy, and add the copy to the destination list */
+ nlt_d= copy_nlatrack(nlt);
+ BLI_addtail(dst, nlt_d);
+ }
+}
- dst->first=dst->last=NULL;
+/* Adding ------------------------------------------- */
- BLI_duplicatelist (dst, src);
+/* Add a NLA Track to the given AnimData
+ * - prev: NLA-Track to add the new one after
+ */
+NlaTrack *add_nlatrack (AnimData *adt, NlaTrack *prev)
+{
+ NlaTrack *nlt;
+
+ /* sanity checks */
+ if (adt == NULL)
+ return NULL;
+
+ /* allocate new track */
+ nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
+
+ /* set settings requiring the track to not be part of the stack yet */
+ nlt->flag = NLATRACK_SELECTED;
+ nlt->index= BLI_countlist(&adt->nla_tracks);
+
+ /* add track to stack, and make it the active one */
+ if (prev)
+ BLI_insertlinkafter(&adt->nla_tracks, prev, nlt);
+ else
+ BLI_addtail(&adt->nla_tracks, nlt);
+ BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
+
+ /* must have unique name, but we need to seed this */
+ sprintf(nlt->name, "NlaTrack");
+ BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64);
+
+ /* return the new track */
+ return nlt;
+}
- /* Update specific data */
- if (!dst->first)
- return;
+/* Add a NLA Strip referencing the given Action */
+NlaStrip *add_nlastrip (bAction *act)
+{
+ NlaStrip *strip;
+
+ /* sanity checks */
+ if (act == NULL)
+ return NULL;
+
+ /* allocate new strip */
+ strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
+
+ /* generic settings
+ * - selected flag to highlight this to the user
+ * - auto-blends to ensure that blend in/out values are automatically
+ * determined by overlaps of strips
+ * - (XXX) synchronisation of strip-length in accordance with changes to action-length
+ * is not done though, since this should only really happens in editmode for strips now
+ * though this decision is still subject to further review...
+ */
+ strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
+
+ /* assign the action reference */
+ strip->act= act;
+ id_us_plus(&act->id);
+
+ /* determine initial range
+ * - strip length cannot be 0... ever...
+ */
+ calc_action_range(strip->act, &strip->actstart, &strip->actend, 1);
+
+ strip->start = strip->actstart;
+ strip->end = (IS_EQ(strip->actstart, strip->actend)) ? (strip->actstart + 1.0f): (strip->actend);
+
+ /* strip should be referenced as-is */
+ strip->scale= 1.0f;
+ strip->repeat = 1.0f;
+
+ /* return the new strip */
+ return strip;
+}
- for (strip = dst->first; strip; strip=strip->next){
- if (strip->act)
- strip->act->id.us++;
- if (strip->ipo)
- strip->ipo->id.us++;
- if (strip->modifiers.first) {
- ListBase listb;
- BLI_duplicatelist (&listb, &strip->modifiers);
- strip->modifiers= listb;
- }
+/* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
+NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
+{
+ NlaStrip *strip;
+ NlaTrack *nlt;
+
+ /* sanity checks */
+ if ELEM(NULL, adt, act)
+ return NULL;
+
+ /* create a new NLA strip */
+ strip= add_nlastrip(act);
+ if (strip == NULL)
+ return NULL;
+
+ /* firstly try adding strip to last track, but if that fails, add to a new track */
+ if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) {
+ /* trying to add to the last track failed (no track or no space),
+ * so add a new track to the stack, and add to that...
+ */
+ nlt= add_nlatrack(adt, NULL);
+ BKE_nlatrack_add_strip(nlt, strip);
}
+
+ /* returns the strip added */
+ return strip;
}
-/* from editnla, for convert_action_to_strip -- no UI code so should be ok here.. */
-void find_stridechannel(Object *ob, bActionStrip *strip)
+/* *************************************************** */
+/* Basic Utilities */
+
+/* NLA-Tracks ---------------------------------------- */
+
+/* Find the active NLA-track for the given stack */
+NlaTrack *BKE_nlatrack_find_active (ListBase *tracks)
{
- if(ob && ob->pose) {
- bPoseChannel *pchan;
- for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
- if(pchan->flag & POSE_STRIDE)
- break;
- if(pchan)
- BLI_strncpy(strip->stridechannel, pchan->name, 32);
- else
- strip->stridechannel[0]= 0;
+ NlaTrack *nlt;
+
+ /* sanity check */
+ if ELEM(NULL, tracks, tracks->first)
+ return NULL;
+
+ /* try to find the first active track */
+ for (nlt= tracks->first; nlt; nlt= nlt->next) {
+ if (nlt->flag & NLATRACK_ACTIVE)
+ return nlt;
}
+
+ /* none found */
+ return NULL;
}
-//called by convert_nla / bpy api with an object with the action to be converted to a new strip
-bActionStrip *convert_action_to_strip (Object *ob)
+/* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
+ * that has this status in its AnimData block.
+ */
+void BKE_nlatrack_solo_toggle (AnimData *adt, NlaTrack *nlt)
{
- bActionStrip *nstrip;
-
- /* Make new actionstrip */
- nstrip = MEM_callocN(sizeof(bActionStrip), "bActionStrip");
-
- /* Link the action to the nstrip */
- nstrip->act = ob->action;
- id_us_plus(&nstrip->act->id);
- calc_action_range(nstrip->act, &nstrip->actstart, &nstrip->actend, 1);
- nstrip->start = nstrip->actstart;
- nstrip->end = nstrip->actend;
- nstrip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION;
-
- find_stridechannel(ob, nstrip);
- //set_active_strip(ob, nstrip); /* is in editnla as does UI calls */
-
- nstrip->repeat = 1.0;
+ NlaTrack *nt;
+
+ /* sanity check */
+ if ELEM(NULL, adt, adt->nla_tracks.first)
+ return;
+
+ /* firstly, make sure 'solo' flag for all tracks is disabled */
+ for (nt= adt->nla_tracks.first; nt; nt= nt->next) {
+ if (nt != nlt)
+ nt->flag &= ~NLATRACK_SOLO;
+ }
+
+ /* now, enable 'solo' for the given track if appropriate */
+ if (nlt) {
+ /* toggle solo status */
+ nlt->flag ^= NLATRACK_SOLO;
+
+ /* set or clear solo-status on AnimData */
+ if (nlt->flag & NLATRACK_SOLO)
+ adt->flag |= ADT_NLA_SOLO_TRACK;
+ else
+ adt->flag &= ~ADT_NLA_SOLO_TRACK;
+ }
+ else
+ adt->flag &= ~ADT_NLA_SOLO_TRACK;
+}
- if(ob->nlastrips.first == NULL)
- ob->nlaflag |= OB_NLA_OVERRIDE;
+/* Make the given NLA-track the active one for the given stack. If no track is provided,
+ * this function can be used to simply deactivate all the NLA tracks in the given stack too.
+ */
+void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
+{
+ NlaTrack *nlt;
- BLI_addtail(&ob->nlastrips, nstrip);
- return nstrip; /* is created, malloced etc. here so is safe to just return the pointer?
- this is needed for setting this active in UI, and probably useful for API too */
+ /* sanity check */
+ if ELEM(NULL, tracks, tracks->first)
+ return;
+ /* deactive all the rest */
+ for (nlt= tracks->first; nlt; nlt= nlt->next)
+ nlt->flag &= ~NLATRACK_ACTIVE;
+
+ /* set the given one as the active one */
+ if (nlt_a)
+ nlt_a->flag |= NLATRACK_ACTIVE;
}
+/* Check if there is any space in the last track to add the given strip */
+short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
+{
+ NlaStrip *strip;
+
+ /* sanity checks */
+ if ((nlt == NULL) || IS_EQ(start, end))
+ return 0;
+ if (start > end) {
+ puts("BKE_nlatrack_has_space error... start and end arguments swapped");
+ SWAP(float, start, end);
+ }
+
+ /* loop over NLA strips checking for any overlaps with this area... */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ /* if start frame of strip is past the target end-frame, that means that
+ * we've gone past the window we need to check for, so things are fine
+ */
+ if (strip->start > end)
+ return 1;
+
+ /* if the end of the strip is greater than either of the boundaries, the range
+ * must fall within the extents of the strip
+ */
+ if ((strip->end > start) || (strip->end > end))
+ return 0;
+ }
+
+ /* if we are still here, we haven't encountered any overlapping strips */
+ return 1;
+}
-/* not strip itself! */
-void free_actionstrip(bActionStrip* strip)
+/* Rearrange the strips in the track so that they are always in order
+ * (usually only needed after a strip has been moved)
+ */
+void BKE_nlatrack_sort_strips (NlaTrack *nlt)
{
- if (!strip)
+ ListBase tmp = {NULL, NULL};
+ NlaStrip *strip, *sstrip;
+
+ /* sanity checks */
+ if ELEM(NULL, nlt, nlt->strips.first)
return;
+
+ /* we simply perform insertion sort on this list, since it is assumed that per track,
+ * there are only likely to be at most 5-10 strips
+ */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ short not_added = 1;
+
+ /* remove this strip from the list, and add it to the new list, searching from the end of
+ * the list, assuming that the lists are in order
+ */
+ BLI_remlink(&nlt->strips, strip);
+
+ for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) {
+ /* check if add after */
+ if (sstrip->end < strip->start) {
+ BLI_insertlinkafter(&tmp, sstrip, strip);
+ not_added= 0;
+ break;
+ }
+ }
+
+ /* add before first? */
+ if (not_added)
+ BLI_addhead(&tmp, strip);
+ }
+
+ /* reassign the start and end points of the strips */
+ nlt->strips.first= tmp.first;
+ nlt->strips.last= tmp.last;
+}
- if (strip->act){
- strip->act->id.us--;
- strip->act = NULL;
+/* Add the given NLA-Strip to the given NLA-Track, assuming that it
+ * isn't currently attached to another one
+ */
+short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip)
+{
+ NlaStrip *ns;
+ short not_added = 1;
+
+ /* sanity checks */
+ if ELEM(NULL, nlt, strip)
+ return 0;
+
+ /* check if any space to add */
+ if (BKE_nlatrack_has_space(nlt, strip->start, strip->end)==0)
+ return 0;
+
+ /* find the right place to add the strip to the nominated track */
+ for (ns= nlt->strips.first; ns; ns= ns->next) {
+ /* if current strip occurs after the new strip, add it before */
+ if (ns->start > strip->end) {
+ BLI_insertlinkbefore(&nlt->strips, ns, strip);
+ not_added= 0;
+ break;
+ }
}
- if (strip->ipo){
- strip->ipo->id.us--;
- strip->ipo = NULL;
+ if (not_added) {
+ /* just add to the end of the list of the strips then... */
+ BLI_addtail(&nlt->strips, strip);
}
- if (strip->modifiers.first) {
- BLI_freelistN(&strip->modifiers);
+
+ /* added... */
+ return 1;
+}
+
+/* NLA Strips -------------------------------------- */
+
+/* Find the active NLA-strip within the given track */
+NlaStrip *BKE_nlastrip_find_active (NlaTrack *nlt)
+{
+ NlaStrip *strip;
+
+ /* sanity check */
+ if ELEM(NULL, nlt, nlt->strips.first)
+ return NULL;
+
+ /* try to find the first active strip */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ if (strip->flag & NLASTRIP_FLAG_ACTIVE)
+ return strip;
}
+ /* none found */
+ return NULL;
}
-void free_nlastrips (ListBase *nlalist)
+/* Does the given NLA-strip fall within the given bounds (times)? */
+short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max)
{
- bActionStrip *strip;
+ const float stripLen= (strip) ? strip->end - strip->start : 0.0f;
+ const float boundsLen= (float)fabs(max - min);
+
+ /* sanity checks */
+ if ((strip == NULL) || IS_EQ(stripLen, 0.0f) || IS_EQ(boundsLen, 0.0f))
+ return 0;
+
+ /* only ok if at least part of the strip is within the bounding window
+ * - first 2 cases cover when the strip length is less than the bounding area
+ * - second 2 cases cover when the strip length is greater than the bounding area
+ */
+ if ( (stripLen < boundsLen) &&
+ !(IN_RANGE(strip->start, min, max) ||
+ IN_RANGE(strip->end, min, max)) )
+ {
+ return 0;
+ }
+ if ( (stripLen > boundsLen) &&
+ !(IN_RANGE(min, strip->start, strip->end) ||
+ IN_RANGE(max, strip->start, strip->end)) )
+ {
+ return 0;
+ }
+
+ /* should be ok! */
+ return 1;
+}
+
+/* Is the given NLA-strip the first one to occur for the given AnimData block */
+// TODO: make this an api method if necesary, but need to add prefix first
+short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
+{
+ NlaTrack *nlt;
+ NlaStrip *ns;
+
+ /* sanity checks */
+ if ELEM(NULL, adt, strip)
+ return 0;
+
+ /* check if strip has any strips before it */
+ if (strip->prev)
+ return 0;
+
+ /* check other tracks to see if they have a strip that's earlier */
+ // TODO: or should we check that the strip's track is also the first?
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+ /* only check the first strip, assuming that they're all in order */
+ ns= nlt->strips.first;
+ if (ns) {
+ if (ns->start < strip->start)
+ return 0;
+ }
+ }
+
+ /* should be first now */
+ return 1;
+}
+
+/* Tools ------------------------------------------- */
- if (!nlalist->first)
+/* For the given AnimData block, add the active action to the NLA
+ * stack (i.e. 'push-down' action). The UI should only allow this
+ * for normal editing only (i.e. not in editmode for some strip's action),
+ * so no checks for this are performed.
+ */
+// TODO: maybe we should have checks for this too...
+void BKE_nla_action_pushdown (AnimData *adt)
+{
+ NlaStrip *strip;
+
+ /* sanity checks */
+ // TODO: need to report the error for this
+ if ELEM(NULL, adt, adt->action)
return;
+
+ /* if the action is empty, we also shouldn't try to add to stack,
+ * as that will cause us grief down the track
+ */
+ // TODO: what about modifiers?
+ if (action_has_motion(adt->action) == 0) {
+ printf("BKE_nla_action_pushdown(): action has no data \n");
+ return;
+ }
+
+ /* add a new NLA strip to the track, which references the active action */
+ strip= add_nlastrip_to_stack(adt, adt->action);
+
+ /* do other necessary work on strip */
+ if (strip) {
+ /* clear reference to action now that we've pushed it onto the stack */
+ adt->action->id.us--;
+ adt->action= NULL;
+
+ /* if the strip is the first one in the track it lives in, check if there
+ * are strips in any other tracks that may be before this, and set the extend
+ * mode accordingly
+ */
+ if (nlastrip_is_first(adt, strip) == 0) {
+ /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
+ * so that it doesn't override strips in previous tracks
+ */
+ strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
+ }
+ }
+}
- /* Do any specific freeing */
- for (strip=nlalist->first; strip; strip=strip->next)
- {
- free_actionstrip (strip);
- };
- /* Free the whole list */
- BLI_freelistN(nlalist);
+/* Find the active strip + track combo, and set them up as the tweaking track,
+ * and return if successful or not.
+ */
+short BKE_nla_tweakmode_enter (AnimData *adt)
+{
+ NlaTrack *nlt, *activeTrack=NULL;
+ NlaStrip *strip, *activeStrip=NULL;
+
+ /* verify that data is valid */
+ if ELEM(NULL, adt, adt->nla_tracks.first)
+ return 0;
+
+ /* if block is already in tweakmode, just leave, but we should report
+ * that this block is in tweakmode (as our returncode)
+ */
+ // FIXME: hopefully the flag is correct!
+ if (adt->flag & ADT_NLA_EDIT_ON)
+ return 1;
+
+ /* go over the tracks, finding the active one, and its active strip
+ * - if we cannot find both, then there's nothing to do
+ */
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+ /* check if active */
+ if (nlt->flag & NLATRACK_ACTIVE) {
+ /* store reference to this active track */
+ activeTrack= nlt;
+
+ /* now try to find active strip */
+ activeStrip= BKE_nlastrip_find_active(nlt);
+ break;
+ }
+ }
+ if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
+ printf("NLA tweakmode enter - neither active requirement found \n");
+ return 0;
+ }
+
+ /* go over all the tracks up to the active one, tagging each strip that uses the same
+ * action as the active strip, but leaving everything else alone
+ */
+ for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) {
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ if (strip->act == activeStrip->act)
+ strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
+ else
+ strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; // XXX probably don't need to clear this...
+ }
+ }
+
+
+ /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled
+ * - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
+ */
+ for (nlt= activeTrack; nlt; nlt= nlt->next)
+ nlt->flag |= NLATRACK_DISABLED;
+
+ /* handle AnimData level changes:
+ * - 'real' active action to temp storage (no need to change user-counts)
+ * - action of active strip set to be the 'active action', and have its usercount incremented
+ * - editing-flag for this AnimData block should also get turned on (for more efficient restoring)
+ */
+ adt->tmpact= adt->action;
+ adt->action= activeStrip->act;
+ id_us_plus(&activeStrip->act->id);
+ adt->flag |= ADT_NLA_EDIT_ON;
+
+ /* done! */
+ return 1;
+}
+
+/* Exit tweakmode for this AnimData block */
+void BKE_nla_tweakmode_exit (AnimData *adt)
+{
+ NlaTrack *nlt;
+
+ /* verify that data is valid */
+ if ELEM(NULL, adt, adt->nla_tracks.first)
+ return;
+
+ /* hopefully the flag is correct - skip if not on */
+ if ((adt->flag & ADT_NLA_EDIT_ON) == 0)
+ return;
+
+ // TODO: need to sync the user-strip with the new state of the action!
+
+ /* for all NLA-tracks, clear the 'disabled' flag */
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
+ nlt->flag &= ~NLATRACK_DISABLED;
+
+ /* handle AnimData level changes:
+ * - 'temporary' active action needs its usercount decreased, since we're removing this reference
+ * - 'real' active action is restored from storage
+ * - storage pointer gets cleared (to avoid having bad notes hanging around)
+ * - editing-flag for this AnimData block should also get turned off
+ */
+ if (adt->action) adt->action->id.us--;
+ adt->action= adt->tmpact;
+ adt->tmpact= NULL;
+ adt->flag &= ~ADT_NLA_EDIT_ON;
}
+
+/* *************************************************** */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 81bd78f1851..c2916bc2231 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1198,18 +1198,12 @@ Object *copy_object(Object *ob)
armature_rebuild_pose(obn, obn->data);
}
copy_defgroups(&obn->defbase, &ob->defbase);
-#if 0 // XXX old animation system
- copy_nlastrips(&obn->nlastrips, &ob->nlastrips);
-#endif // XXX old animation system
copy_constraints(&obn->constraints, &ob->constraints);
/* increase user numbers */
id_us_plus((ID *)obn->data);
-#if 0 // XXX old animation system
- id_us_plus((ID *)obn->ipo);
- id_us_plus((ID *)obn->action);
-#endif // XXX old animation system
id_us_plus((ID *)obn->dup_group);
+ // FIXME: add this for animdata too...
for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1502b475350..74226cabba6 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1667,10 +1667,26 @@ static void lib_link_constraint_channels(FileData *fd, ID *id, ListBase *chanbas
/* Data Linking ----------------------------- */
+static void lib_link_fmodifiers(FileData *fd, ID *id, ListBase *list)
+{
+ FModifier *fcm;
+
+ for (fcm= list->first; fcm; fcm= fcm->next) {
+ /* data for specific modifiers */
+ switch (fcm->type) {
+ case FMODIFIER_TYPE_PYTHON:
+ {
+ FMod_Python *data= (FMod_Python *)fcm->data;
+ data->script = newlibadr(fd, id->lib, data->script);
+ }
+ break;
+ }
+ }
+}
+
static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
{
FCurve *fcu;
- FModifier *fcm;
/* relink ID-block references... */
for (fcu= list->first; fcu; fcu= fcu->next) {
@@ -1684,16 +1700,45 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
}
/* modifiers */
- for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
- /* data for specific modifiers */
- switch (fcm->type) {
- case FMODIFIER_TYPE_PYTHON:
- {
- FMod_Python *data= (FMod_Python *)fcm->data;
- data->script = newlibadr(fd, id->lib, data->script);
- }
- break;
+ lib_link_fmodifiers(fd, id, &fcu->modifiers);
+ }
+}
+
+
+/* NOTE: this assumes that link_list has already been called on the list */
+static void direct_link_fmodifiers(FileData *fd, ListBase *list)
+{
+ FModifier *fcm;
+
+ for (fcm= list->first; fcm; fcm= fcm->next) {
+ /* relink general data */
+ fcm->data = newdataadr(fd, fcm->data);
+ fcm->edata= NULL;
+
+ /* do relinking of data for specific types */
+ switch (fcm->type) {
+ case FMODIFIER_TYPE_GENERATOR:
+ {
+ FMod_Generator *data= (FMod_Generator *)fcm->data;
+
+ data->coefficients= newdataadr(fd, data->coefficients);
+ }
+ break;
+ case FMODIFIER_TYPE_ENVELOPE:
+ {
+ FMod_Envelope *data= (FMod_Envelope *)fcm->data;
+
+ data->data= newdataadr(fd, data->data);
}
+ break;
+ case FMODIFIER_TYPE_PYTHON:
+ {
+ FMod_Python *data= (FMod_Python *)fcm->data;
+
+ data->prop = newdataadr(fd, data->prop);
+ IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ }
+ break;
}
}
}
@@ -1702,7 +1747,6 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
static void direct_link_fcurves(FileData *fd, ListBase *list)
{
FCurve *fcu;
- FModifier *fcm;
/* link F-Curve data to F-Curve again (non ID-libs) */
for (fcu= list->first; fcu; fcu= fcu->next) {
@@ -1730,37 +1774,7 @@ static void direct_link_fcurves(FileData *fd, ListBase *list)
/* modifiers */
link_list(fd, &fcu->modifiers);
- for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
- /* relink general data */
- fcm->data = newdataadr(fd, fcm->data);
- fcm->edata= NULL;
-
- /* do relinking of data for specific types */
- switch (fcm->type) {
- case FMODIFIER_TYPE_GENERATOR:
- {
- FMod_Generator *data= (FMod_Generator *)fcm->data;
-
- data->coefficients= newdataadr(fd, data->coefficients);
- }
- break;
- case FMODIFIER_TYPE_ENVELOPE:
- {
- FMod_Envelope *data= (FMod_Envelope *)fcm->data;
-
- data->data= newdataadr(fd, data->data);
- }
- break;
- case FMODIFIER_TYPE_PYTHON:
- {
- FMod_Python *data= (FMod_Python *)fcm->data;
-
- data->prop = newdataadr(fd, data->prop);
- IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
- break;
- }
- }
+ direct_link_fmodifiers(fd, &fcu->modifiers);
}
}
@@ -1812,6 +1826,44 @@ static void direct_link_action(FileData *fd, bAction *act)
}
}
+
+static void lib_link_nladata (FileData *fd, ID *id, ListBase *list)
+{
+ NlaTrack *nlt;
+ NlaStrip *strip;
+
+ /* we only acare about the NLA strips inside the tracks */
+ for (nlt= list->first; nlt; nlt= nlt->next) {
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ /* reassign the counted-reference to action */
+ strip->act = newlibadr_us(fd, id->lib, strip->act);
+ }
+ }
+}
+
+/* NOTE: this assumes that link_list has already been called on the list */
+static void direct_link_nladata(FileData *fd, ListBase *list)
+{
+ NlaTrack *nlt;
+ NlaStrip *strip;
+
+ for (nlt= list->first; nlt; nlt= nlt->next) {
+ /* relink list of strips */
+ link_list(fd, &nlt->strips);
+
+ /* relink strip data */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ /* strip's F-Curves */
+ link_list(fd, &strip->fcurves);
+ direct_link_fcurves(fd, &strip->fcurves);
+
+ /* strip's F-Modifiers */
+ link_list(fd, &strip->modifiers);
+ direct_link_fcurves(fd, &strip->modifiers);
+ }
+ }
+}
+
/* ------- */
static void lib_link_keyingsets(FileData *fd, ID *id, ListBase *list)
@@ -1854,6 +1906,7 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
/* link action data */
adt->action= newlibadr_us(fd, id->lib, adt->action);
+ adt->tmpact= newlibadr_us(fd, id->lib, adt->tmpact);
/* link drivers */
lib_link_fcurves(fd, id, &adt->drivers);
@@ -1861,7 +1914,7 @@ static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
/* overrides don't have lib-link for now, so no need to do anything */
/* link NLA-data */
- // TODO...
+ lib_link_nladata(fd, id, &adt->nla_tracks);
}
static void direct_link_animdata(FileData *fd, AnimData *adt)
@@ -1878,7 +1931,8 @@ static void direct_link_animdata(FileData *fd, AnimData *adt)
// TODO...
/* link NLA-data */
- // TODO...
+ link_list(fd, &adt->nla_tracks);
+ direct_link_nladata(fd, &adt->nla_tracks);
}
/* ************ READ NODE TREE *************** */
@@ -4701,6 +4755,11 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
sipo->ads= newdataadr(fd, sipo->ads);
sipo->ghostCurves.first= sipo->ghostCurves.last= NULL;
}
+ else if (sl->spacetype==SPACE_NLA) {
+ SpaceNla *snla= (SpaceNla*)sl;
+
+ snla->ads= newdataadr(fd, snla->ads);
+ }
else if (sl->spacetype==SPACE_OUTLINER) {
SpaceOops *soops= (SpaceOops*) sl;
@@ -9497,9 +9556,12 @@ static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list)
static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
{
FCurve *fcd;
+ NlaTrack *nlt;
+ NlaStrip *strip;
/* own action */
expand_doit(fd, mainvar, adt->action);
+ expand_doit(fd, mainvar, adt->tmpact);
/* drivers - assume that these F-Curves have driver data to be in this list... */
for (fcd= adt->drivers.first; fcd; fcd= fcd->next) {
@@ -9509,6 +9571,12 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
for (dtar= driver->targets.first; dtar; dtar= dtar->next)
expand_doit(fd, mainvar, dtar->id);
}
+
+ /* nla-data - referenced actions */
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+ for (strip= nlt->strips.first; strip; strip= strip->next)
+ expand_doit(fd, mainvar, strip->act);
+ }
}
static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part)
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index f8112406e80..0c385911721 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -760,10 +760,59 @@ static void write_actuators(WriteData *wd, ListBase *lb)
}
}
+static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
+{
+ FModifier *fcm;
+
+ /* Modifiers */
+ for (fcm= fmodifiers->first; fcm; fcm= fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* Write the specific data */
+ if (fmi && fcm->data) {
+ /* firstly, just write the plain fmi->data struct */
+ writestruct(wd, DATA, fmi->structName, 1, fcm->data);
+
+ /* do any modifier specific stuff */
+ switch (fcm->type) {
+ case FMODIFIER_TYPE_GENERATOR:
+ {
+ FMod_Generator *data= (FMod_Generator *)fcm->data;
+
+ /* write coefficients array */
+ if (data->coefficients)
+ writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
+ }
+ break;
+ case FMODIFIER_TYPE_ENVELOPE:
+ {
+ FMod_Envelope *data= (FMod_Envelope *)fcm->data;
+
+ /* write envelope data */
+ if (data->data)
+ writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data);
+ }
+ break;
+ case FMODIFIER_TYPE_PYTHON:
+ {
+ FMod_Python *data = (FMod_Python *)fcm->data;
+
+ /* Write ID Properties -- and copy this comment EXACTLY for easy finding
+ of library blocks that implement this.*/
+ IDP_WriteProperty(data->prop, wd);
+ }
+ break;
+ }
+ }
+
+ /* Write the modifier */
+ writestruct(wd, DATA, "FModifier", 1, fcm);
+ }
+}
+
static void write_fcurves(WriteData *wd, ListBase *fcurves)
{
FCurve *fcu;
- FModifier *fcm;
for (fcu=fcurves->first; fcu; fcu=fcu->next) {
/* F-Curve */
@@ -794,50 +843,8 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
}
}
- /* Modifiers */
- for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* Write the specific data */
- if (fmi && fcm->data) {
- /* firstly, just write the plain fmi->data struct */
- writestruct(wd, DATA, fmi->structName, 1, fcm->data);
-
- /* do any modifier specific stuff */
- switch (fcm->type) {
- case FMODIFIER_TYPE_GENERATOR:
- {
- FMod_Generator *data= (FMod_Generator *)fcm->data;
-
- /* write coefficients array */
- if (data->coefficients)
- writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
- }
- break;
- case FMODIFIER_TYPE_ENVELOPE:
- {
- FMod_Envelope *data= (FMod_Envelope *)fcm->data;
-
- /* write envelope data */
- if (data->data)
- writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data);
- }
- break;
- case FMODIFIER_TYPE_PYTHON:
- {
- FMod_Python *data = (FMod_Python *)fcm->data;
-
- /* Write ID Properties -- and copy this comment EXACTLY for easy finding
- of library blocks that implement this.*/
- IDP_WriteProperty(data->prop, wd);
- }
- break;
- }
- }
-
- /* Write the modifier */
- writestruct(wd, DATA, "FModifier", 1, fcm);
- }
+ /* write F-Modifiers */
+ write_fmodifiers(wd, &fcu->modifiers);
}
}
@@ -888,6 +895,29 @@ static void write_keyingsets(WriteData *wd, ListBase *list)
}
}
+static void write_nladata(WriteData *wd, ListBase *nlabase)
+{
+ NlaTrack *nlt;
+ NlaStrip *strip;
+
+ /* write all the tracks */
+ for (nlt= nlabase->first; nlt; nlt= nlt->next) {
+ /* write the track first */
+ writestruct(wd, DATA, "NlaTrack", 1, nlt);
+
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ /* write the strip first */
+ writestruct(wd, DATA, "NlaStrip", 1, strip);
+
+ /* write the strip's F-Curves and modifiers */
+ write_fcurves(wd, &strip->fcurves);
+ write_fmodifiers(wd, &strip->modifiers);
+
+ // TODO write the remaps
+ }
+ }
+}
+
static void write_animdata(WriteData *wd, AnimData *adt)
{
AnimOverride *aor;
@@ -899,14 +929,17 @@ static void write_animdata(WriteData *wd, AnimData *adt)
write_fcurves(wd, &adt->drivers);
/* write overrides */
+ // FIXME: are these needed?
for (aor= adt->overrides.first; aor; aor= aor->next) {
/* overrides consist of base data + rna_path */
writestruct(wd, DATA, "AnimOverride", 1, aor);
writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path);
}
+ // TODO write the remaps (if they are needed)
+
/* write NLA data */
- // XXX todo...
+ write_nladata(wd, &adt->nla_tracks);
}
static void write_constraints(WriteData *wd, ListBase *conlist)
@@ -1876,7 +1909,10 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
writestruct(wd, DATA, "SpaceSound", 1, sl);
}
else if(sl->spacetype==SPACE_NLA){
- writestruct(wd, DATA, "SpaceNla", 1, sl);
+ SpaceNla *snla= (SpaceNla *)sl;
+
+ writestruct(wd, DATA, "SpaceNla", 1, snla);
+ if(snla->ads) writestruct(wd, DATA, "bDopeSheet", 1, snla->ads);
}
else if(sl->spacetype==SPACE_TIME){
writestruct(wd, DATA, "SpaceTime", 1, sl);
diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c
index c52ade1bba8..d753f65ff50 100644
--- a/source/blender/editors/animation/anim_channels.c
+++ b/source/blender/editors/animation/anim_channels.c
@@ -87,43 +87,16 @@
/* ************************************************************************** */
/* CHANNELS API */
-/* -------------------------- Internal Macros ------------------------------- */
-
-/* set/clear/toggle macro
- * - channel - channel with a 'flag' member that we're setting
- * - smode - 0=clear, 1=set, 2=toggle
- * - sflag - bitflag to set
- */
-#define ACHANNEL_SET_FLAG(channel, smode, sflag) \
- { \
- if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \
- else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \
- else (channel)->flag &= ~(sflag); \
- }
-
-/* set/clear/toggle macro, where the flag is negative
- * - channel - channel with a 'flag' member that we're setting
- * - smode - 0=clear, 1=set, 2=toggle
- * - sflag - bitflag to set
- */
-#define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \
- { \
- if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \
- else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag &= ~(sflag); \
- else (channel)->flag |= (sflag); \
- }
-
/* -------------------------- Exposed API ----------------------------------- */
/* Set the given animation-channel as the active one for the active context */
-void ANIM_set_active_channel (void *data, short datatype, int filter, void *channel_data, short channel_type)
+void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
/* try to build list of filtered items */
- // XXX we don't need/supply animcontext for now, since in this case, there's nothing really essential there that isn't already covered
- ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype);
+ ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
if (anim_data.first == NULL)
return;
@@ -149,6 +122,13 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan
ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE);
}
break;
+ case ANIMTYPE_NLATRACK:
+ {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+
+ ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
+ }
+ break;
}
}
@@ -167,6 +147,12 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan
fcu->flag |= FCURVE_ACTIVE;
}
break;
+ case ANIMTYPE_NLATRACK:
+ {
+ NlaTrack *nlt= (NlaTrack *)channel_data;
+ nlt->flag |= NLATRACK_ACTIVE;
+ }
+ break;
}
}
@@ -217,6 +203,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
if (ale->flag & FCURVE_SELECTED)
sel= ACHANNEL_SETFLAG_CLEAR;
break;
+ case ANIMTYPE_NLATRACK:
+ if (ale->flag & NLATRACK_SELECTED)
+ sel= ACHANNEL_SETFLAG_CLEAR;
+ break;
}
}
}
@@ -263,6 +253,14 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
fcu->flag &= ~FCURVE_ACTIVE;
}
break;
+ case ANIMTYPE_NLATRACK:
+ {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+
+ ACHANNEL_SET_FLAG(nlt, sel, NLATRACK_SELECTED);
+ nlt->flag &= ~NLATRACK_ACTIVE;
+ }
+ break;
}
}
@@ -1218,6 +1216,14 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele
ACHANNEL_SET_FLAG(gpl, selectmode, GP_LAYER_SELECT);
}
break;
+
+ case ANIMTYPE_NLATRACK: /* nla-track */
+ {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+
+ ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED);
+ }
+ break;
}
}
@@ -1474,7 +1480,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* if group is selected now, make group the 'active' one in the visible list */
if (agrp->flag & AGRP_SELECTED)
- ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
}
}
break;
@@ -1520,7 +1526,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
/* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
if (fcu->flag & FCURVE_SELECTED)
- ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
}
}
break;
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index afad396607b..f9c1b1bb42f 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -195,7 +195,7 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
}
}
-/* ----------- Private Stuff - IPO Editor ------------- */
+/* ----------- Private Stuff - Graph Editor ------------- */
/* Get data being edited in Graph Editor (depending on current 'mode') */
static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
@@ -237,6 +237,26 @@ static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
}
}
+/* ----------- Private Stuff - NLA Editor ------------- */
+
+/* Get data being edited in Graph Editor (depending on current 'mode') */
+static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla)
+{
+ /* init dopesheet data if non-existant (i.e. for old files) */
+ if (snla->ads == NULL)
+ snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
+
+ /* sync settings with current view status, then return appropriate data */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ snla->ads->source= (ID *)ac->scene;
+ snla->ads->filterflag |= ADS_FILTER_ONLYNLA;
+
+ ac->datatype= ANIMCONT_NLA;
+ ac->data= snla->ads;
+
+ return 1;
+}
+
/* ----------- Public API --------------- */
/* Obtain current anim-data context, given that context info from Blender context has already been set
@@ -264,6 +284,13 @@ short ANIM_animdata_context_getdata (bAnimContext *ac)
ok= graphedit_get_context(ac, sipo);
}
break;
+
+ case SPACE_NLA:
+ {
+ SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
+ ok= nlaedit_get_context(ac, snla);
+ }
+ break;
}
}
@@ -313,6 +340,68 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
/* quick macro to test if AnimData is usable for drivers */
#define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
+/* quick macro to test if AnimData is usable for NLA */
+#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
+
+
+/* Quick macro to test for all three avove usability tests, performing the appropriate provided
+ * action for each when the AnimData context is appropriate.
+ *
+ * Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
+ *
+ * For this to work correctly, a standard set of data needs to be available within the scope that this
+ * gets called in:
+ * - ListBase anim_data;
+ * - bDopeSheet *ads;
+ * - bAnimListElem *ale;
+ * - int items;
+ *
+ * - id: ID block which should have an AnimData pointer following it immediately, to use
+ * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
+ * - nlaOk: line or block of code to execute for NLA case
+ * - driversOk: line or block of code to execute for Drivers case
+ * - keysOk: line or block of code for Keyframes case
+ */
+#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
+ {\
+ if (filter_mode & ANIMFILTER_ANIMDATA) {\
+ if ((id)->adt) {\
+ adtOk\
+ }\
+ }\
+ else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\
+ if (ANIMDATA_HAS_NLA(id)) {\
+ nlaOk\
+ }\
+ else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) {\
+ nlaOk\
+ }\
+ }\
+ else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\
+ if (ANIMDATA_HAS_DRIVERS(id)) {\
+ driversOk\
+ }\
+ }\
+ else {\
+ if (ANIMDATA_HAS_KEYS(id)) {\
+ keysOk\
+ }\
+ }\
+ }
+
+
+/* quick macro to add a pointer to an AnimData block as a channel */
+#define ANIMDATA_ADD_ANIMDATA(id) \
+ {\
+ ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\
+ if (ale) {\
+ BLI_addtail(anim_data, ale);\
+ items++;\
+ }\
+ }
+
+
+
/* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
#define ANIMCHANNEL_SELOK(test_func) \
( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
@@ -494,6 +583,25 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
ale->datatype= ALE_GPFRAME;
}
break;
+
+ case ANIMTYPE_NLATRACK:
+ {
+ NlaTrack *nlt= (NlaTrack *)data;
+
+ ale->flag= nlt->flag;
+
+ // XXX or should this be done some other way?
+ ale->key_data= &nlt->strips;
+ ale->datatype= ALE_NLASTRIP;
+ }
+ break;
+ case ANIMTYPE_NLAACTION:
+ {
+ /* nothing to include for now... nothing editable from NLA-perspective here */
+ ale->key_data= NULL;
+ ale->datatype= ALE_NONE;
+ }
+ break;
}
}
@@ -522,7 +630,6 @@ static int animdata_filter_fcurves (ListBase *anim_data, FCurve *first, bActionG
if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) ) {
/* only include if this curve is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
- /* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */
ale= make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
if (ale) {
@@ -610,6 +717,83 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
return items;
}
+/* Include NLA-Data for NLA-Editor:
+ * - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display
+ * Although the evaluation order is from the first track to the last and then apply the Action on top,
+ * we present this in the UI as the Active Action followed by the last track to the first so that we
+ * get the evaluation order presented as per a stack.
+ * - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
+ * order, i.e. first to last. Otherwise, some tools may get screwed up.
+ */
+static int animdata_filter_nla (ListBase *anim_data, AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
+{
+ bAnimListElem *ale;
+ NlaTrack *nlt;
+ NlaTrack *first=NULL, *next=NULL;
+ int items = 0;
+
+ /* if showing channels, include active action */
+ if (filter_mode & ANIMFILTER_CHANNELS) {
+ /* there isn't really anything editable here, so skip if need editable */
+ // TODO: currently, selection isn't checked since it doesn't matter
+ if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
+ /* just add the action track now (this MUST appear for drawing)
+ * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
+ * overwrite this with the real value - REVIEW THIS...
+ */
+ ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id);
+ ale->data= (adt->action) ? adt->action : NULL;
+
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* first track to include will be the last one if we're filtering by channels */
+ first= adt->nla_tracks.last;
+ }
+ else {
+ /* first track to include will the the first one (as per normal) */
+ first= adt->nla_tracks.first;
+ }
+
+ /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
+ for (nlt= first; nlt; nlt= next) {
+ /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
+ if (filter_mode & ANIMFILTER_CHANNELS)
+ next= nlt->prev;
+ else
+ next= nlt->next;
+
+ /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now
+ * - active track should still get shown though (even though it has disabled flag set)
+ */
+ // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel
+ if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE))
+ continue;
+
+ /* only work with this channel and its subchannels if it is editable */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
+ /* only include this track if selected in a way consistent with the filtering requirements */
+ if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
+ /* only include if this track is active */
+ if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
+ ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id);
+
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype, ID *owner_id)
{
bAnimListElem *ale;
@@ -752,19 +936,19 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
/* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
for (a=0; a < ob->totcol; a++) {
Material *ma= give_current_material(ob, a);
+ short ok = 0;
/* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
if (ELEM(NULL, ma, ma->adt))
continue;
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) {
- if (ANIMDATA_HAS_KEYS(ma) == 0)
- continue;
- }
- else {
- if (ANIMDATA_HAS_DRIVERS(ma) == 0)
- continue;
- }
+ /* check if ok */
+ ANIMDATA_FILTER_CASES(ma,
+ { /* AnimData blocks - do nothing... */ },
+ ok=1;,
+ ok=1;,
+ ok=1;)
+ if (ok == 0) continue;
/* make a temp list elem for this */
ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache");
@@ -801,16 +985,13 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
}
}
- /* add material's F-Curve or Driver channels? */
+ /* add material's animation data */
if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) {
- // XXX the 'owner' info here is still subject to improvement
- items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);
- }
- else {
- // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
- items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);
- }
+ ANIMDATA_FILTER_CASES(ma,
+ { /* AnimData blocks - do nothing... */ },
+ items += animdata_filter_nla(anim_data, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);,
+ items += animdata_filter_fcurves(anim_data, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);,
+ items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
}
}
}
@@ -871,15 +1052,12 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
/* add object-data animation channels? */
if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- /* Action or Drivers? */
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
- // XXX the 'owner' info here is still subject to improvement
- items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);
- }
- else {
- // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
- items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);
- }
+ /* filtering for channels - nla, drivers, keyframes */
+ ANIMDATA_FILTER_CASES(iat,
+ { /* AnimData blocks - do nothing... */ },
+ items+= animdata_filter_nla(anim_data, iat->adt, filter_mode, iat, type, (ID *)iat);,
+ items+= animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);,
+ items += animdata_filter_action(anim_data, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
}
/* return the number of items added to the list */
@@ -889,12 +1067,14 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
bAnimListElem *ale=NULL;
+ AnimData *adt = NULL;
Object *ob= base->object;
Key *key= ob_get_key(ob);
+ short obdata_ok = 0;
int items = 0;
/* add this object as a channel first */
- if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
+ if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
/* check if filtering by selection */
if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL);
@@ -906,76 +1086,79 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
}
/* if collapsed, don't go any further (unless adding keyframes only) */
- if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) )
+ if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
return items;
- /* Action or Drivers */
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
- /* Action? */
- if (ANIMDATA_HAS_KEYS(ob) /*&& !(ads->filterflag & ADS_FILTER_NOACTS)*/) {
- AnimData *adt= ob->adt;
-
- /* include action-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+ /* Action, Drivers, or NLA */
+ if (ob->adt) {
+ adt= ob->adt;
+ ANIMDATA_FILTER_CASES(ob,
+ { /* AnimData blocks - do nothing... */ },
+ { /* nla */
+ /* add NLA tracks */
+ items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+ },
+ { /* drivers */
+ /* include drivers-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
}
- }
-
- /* add F-Curve channels? */
- if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
- // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
- items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
- }
- }
- }
- else {
- /* Drivers */
- if (ANIMDATA_HAS_DRIVERS(ob)) {
- AnimData *adt= ob->adt;
-
- /* include drivers-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+
+ /* add F-Curve channels (drivers are F-Curves) */
+ if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
+ items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
+ }
+ },
+ { /* action (keyframes) */
+ /* include action-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add F-Curve channels? */
+ if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
+ items += animdata_filter_action(anim_data, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
}
}
-
- /* add F-Curve channels (drivers are F-Curves) */
- if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
- // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
- items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
- }
- }
+ );
}
+
/* ShapeKeys? */
if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
- /* Animation or Drivers */
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
- /* include shapekey-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+ adt= key->adt;
+ ANIMDATA_FILTER_CASES(key,
+ { /* AnimData blocks - do nothing... */ },
+ { /* nla */
+ /* add NLA tracks */
+ items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+ },
+ { /* drivers */
+ /* include shapekey-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
}
- }
-
- /* add channels */
- if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
- }
- }
- else {
- /* Drivers */
- if (ANIMDATA_HAS_DRIVERS(key)) {
- AnimData *adt= key->adt;
+ /* add channels */
+ if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+ items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
+ }
+ },
+ { /* action (keyframes) */
/* include shapekey-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
@@ -985,15 +1168,13 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
}
}
- /* add F-Curve channels (drivers are F-Curves) */
- if (FILTER_SKE_OBJD(key)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
- // XXX owner info is messed up now...
- items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)key);
+ /* add channels */
+ if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+ items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
}
}
- }
+ );
}
-
/* Materials? */
if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
@@ -1006,14 +1187,11 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
Camera *ca= (Camera *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) {
- if (ANIMDATA_HAS_KEYS(ca))
- items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
- }
- else {
- if (ANIMDATA_HAS_DRIVERS(ca))
- items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
- }
+ ANIMDATA_FILTER_CASES(ca,
+ { /* AnimData blocks - do nothing... */ },
+ obdata_ok= 1;,
+ obdata_ok= 1;,
+ obdata_ok= 1;)
}
}
break;
@@ -1022,14 +1200,11 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
Lamp *la= (Lamp *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) {
- if (ANIMDATA_HAS_KEYS(la))
- items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
- }
- else {
- if (ANIMDATA_HAS_DRIVERS(la))
- items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
- }
+ ANIMDATA_FILTER_CASES(la,
+ { /* AnimData blocks - do nothing... */ },
+ obdata_ok= 1;,
+ obdata_ok= 1;,
+ obdata_ok= 1;)
}
}
break;
@@ -1038,18 +1213,17 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
Curve *cu= (Curve *)ob->data;
if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS)==0) {
- if (ANIMDATA_HAS_KEYS(cu))
- items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
- }
- else {
- if (ANIMDATA_HAS_DRIVERS(cu))
- items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
- }
+ ANIMDATA_FILTER_CASES(cu,
+ { /* AnimData blocks - do nothing... */ },
+ obdata_ok= 1;,
+ obdata_ok= 1;,
+ obdata_ok= 1;)
}
}
break;
}
+ if (obdata_ok)
+ items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode);
/* return the number of items added to the list */
return items;
@@ -1058,11 +1232,12 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
World *wo= sce->world;
+ AnimData *adt= NULL;
bAnimListElem *ale;
int items = 0;
/* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
- if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
+ if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
/* check if filtering by selection */
if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
@@ -1074,77 +1249,63 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
}
/* if collapsed, don't go any further (unless adding keyframes only) */
- if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & ANIMFILTER_CURVESONLY) )
+ if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
return items;
- /* Action or Drivers */
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
- /* Action? */
- if (ANIMDATA_HAS_KEYS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) {
- AnimData *adt= sce->adt;
-
- /* include action-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+ /* Action, Drivers, or NLA for Scene */
+ if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
+ adt= sce->adt;
+ ANIMDATA_FILTER_CASES(sce,
+ { /* AnimData blocks - do nothing... */ },
+ { /* nla */
+ /* add NLA tracks */
+ items += animdata_filter_nla(anim_data, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
+ },
+ { /* drivers */
+ /* include drivers-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
}
- }
-
- /* add F-Curve channels? */
- if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
- items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
- }
- }
- }
- else {
- /* Drivers */
- if (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE)) {
- AnimData *adt= sce->adt;
-
- /* include drivers-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+
+ /* add F-Curve channels (drivers are F-Curves) */
+ if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
+ }
+ },
+ { /* action */
+ /* include action-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add F-Curve channels? */
+ if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+ items += animdata_filter_action(anim_data, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
}
}
-
- /* add F-Curve channels (drivers are F-Curves) */
- if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
- items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
- }
- }
+ )
}
-
+
/* world */
if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
- /* Animation or Drivers */
- if ((ads->filterflag & ADS_FILTER_ONLYDRIVERS) == 0) {
- AnimData *adt= wo->adt;
-
- /* include world-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add channels */
- if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- items += animdata_filter_action(anim_data, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
- }
- }
- else {
- /* Drivers */
- if (ANIMDATA_HAS_DRIVERS(wo)) {
- AnimData *adt= wo->adt;
-
- /* include shapekey-expand widget? */
+ /* Action, Drivers, or NLA for World */
+ adt= wo->adt;
+ ANIMDATA_FILTER_CASES(wo,
+ { /* AnimData blocks - do nothing... */ },
+ { /* nla */
+ /* add NLA tracks */
+ items += animdata_filter_nla(anim_data, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
+ },
+ { /* drivers */
+ /* include world-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo);
if (ale) {
@@ -1158,8 +1319,23 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
// XXX owner info is messed up now...
items += animdata_filter_fcurves(anim_data, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo);
}
+ },
+ { /* action */
+ /* include world-expand widget? */
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
+ ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
+ if (ale) {
+ BLI_addtail(anim_data, ale);
+ items++;
+ }
+ }
+
+ /* add channels */
+ if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+ items += animdata_filter_action(anim_data, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
+ }
}
- }
+ )
}
/* return the number of items added to the list */
@@ -1171,6 +1347,7 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
{
Scene *sce= (Scene *)ads->source;
Base *base;
+ bAnimListElem *ale;
int items = 0;
/* check that we do indeed have a scene */
@@ -1182,22 +1359,32 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
/* scene-linked animation */
// TODO: sequencer, composite nodes - are we to include those here too?
{
- short sceOk, worOk;
+ short sceOk= 0, worOk= 0;
/* check filtering-flags if ok */
- if (ads->filterflag) {
- if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {
- sceOk= (ANIMDATA_HAS_DRIVERS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE));
- worOk= ((sce->world) && ANIMDATA_HAS_DRIVERS(sce->world) && !(ads->filterflag & ADS_FILTER_NOWOR));
- }
- else {
- sceOk= (ANIMDATA_HAS_KEYS(sce) && !(ads->filterflag & ADS_FILTER_NOSCE));
- worOk= ((sce->world) && ANIMDATA_HAS_KEYS(sce->world) && !(ads->filterflag & ADS_FILTER_NOWOR));
- }
- }
- else {
- sceOk= (ANIMDATA_HAS_KEYS(sce));
- worOk= ((sce->world) && ANIMDATA_HAS_KEYS(sce->world));
+ ANIMDATA_FILTER_CASES(sce,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(sce);
+ sceOk=0;
+ },
+ sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
+ sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
+ sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
+ if (sce->world) {
+ ANIMDATA_FILTER_CASES(sce->world,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(sce->world);
+ worOk=0;
+ },
+ worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
+ worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
+ worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
}
/* check if not all bad (i.e. so there is something to show) */
@@ -1239,13 +1426,33 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
}
/* check filters for datatypes */
- if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {
- actOk= (ANIMDATA_HAS_DRIVERS(ob));
- keyOk= ((key) && ANIMDATA_HAS_DRIVERS(key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS));
- }
- else {
- actOk= ANIMDATA_HAS_KEYS(ob);
- keyOk= ((key) && ANIMDATA_HAS_KEYS(key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS));
+ /* object */
+ actOk= 0;
+ keyOk= 0;
+ ANIMDATA_FILTER_CASES(ob,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(ob);
+ actOk=0;
+ },
+ actOk= 1;,
+ actOk= 1;,
+ actOk= 1;)
+ if (key) {
+ /* shapekeys */
+ ANIMDATA_FILTER_CASES(key,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(key);
+ keyOk=0;
+ },
+ keyOk= 1;,
+ keyOk= 1;,
+ keyOk= 1;)
}
/* materials - only for geometric types */
@@ -1260,18 +1467,20 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
Material *ma= give_current_material(ob, a);
/* if material has relevant animation data, break */
- if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {
- if (ANIMDATA_HAS_DRIVERS(ma)) {
- matOk= 1;
- break;
- }
- }
- else {
- if (ANIMDATA_HAS_KEYS(ma)) {
- matOk= 1;
- break;
- }
- }
+ ANIMDATA_FILTER_CASES(ma,
+ {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(ma);
+ matOk=0;
+ },
+ matOk= 1;,
+ matOk= 1;,
+ matOk= 1;)
+
+ if (matOk)
+ break;
}
}
@@ -1280,19 +1489,52 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
case OB_CAMERA: /* ------- Camera ------------ */
{
Camera *ca= (Camera *)ob->data;
- if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
- dataOk= (ANIMDATA_HAS_DRIVERS(ca) && !(ads->filterflag & ADS_FILTER_NOCAM));
- else
- dataOk= (ANIMDATA_HAS_KEYS(ca) && !(ads->filterflag & ADS_FILTER_NOCAM));
+ dataOk= 0;
+ ANIMDATA_FILTER_CASES(ca,
+ if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(ca);
+ dataOk=0;
+ },
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
}
break;
case OB_LAMP: /* ---------- Lamp ----------- */
{
Lamp *la= (Lamp *)ob->data;
- if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
- dataOk= (ANIMDATA_HAS_DRIVERS(la) && !(ads->filterflag & ADS_FILTER_NOLAM));
- else
- dataOk= (ANIMDATA_HAS_KEYS(la) && !(ads->filterflag & ADS_FILTER_NOLAM));
+ dataOk= 0;
+ ANIMDATA_FILTER_CASES(la,
+ if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(la);
+ dataOk=0;
+ },
+ dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
+ dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
+ dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
+ }
+ break;
+ case OB_CURVE: /* ------- Curve ---------- */
+ {
+ Curve *cu= (Curve *)ob->data;
+ dataOk= 0;
+ ANIMDATA_FILTER_CASES(cu,
+ if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
+ /* for the special AnimData blocks only case, we only need to add
+ * the block if it is valid... then other cases just get skipped (hence ok=0)
+ */
+ ANIMDATA_ADD_ANIMDATA(cu);
+ dataOk=0;
+ },
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
+ dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
}
break;
default: /* --- other --- */
@@ -1400,6 +1642,7 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode
case ANIMCONT_DOPESHEET:
case ANIMCONT_FCURVES:
case ANIMCONT_DRIVERS:
+ case ANIMCONT_NLA:
items= animdata_filter_dopesheet(anim_data, data, filter_mode);
break;
}
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index cfbd6d2bced..144cd68f6df 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -412,8 +412,6 @@ void scene_to_keylist(Scene *sce, ListBase *keys, ListBase *blocks, ActKeysInc *
/* get filterflag */
if (ads)
filterflag= ads->filterflag;
- else if ((aki) && (aki->actmode == -1)) /* only set like this by NLA */
- filterflag= ADS_FILTER_NLADUMMY;
else
filterflag= 0;
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 8243629b4a6..77826eca87a 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -128,6 +128,10 @@ static short agrp_keys_bezier_loop(BeztEditData *bed, bActionGroup *agrp, BeztEd
{
FCurve *fcu;
+ /* sanity check */
+ if (agrp == NULL)
+ return 0;
+
/* only iterate over the F-Curves that are in this group */
for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
@@ -142,6 +146,10 @@ static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc
{
FCurve *fcu;
+ /* sanity check */
+ if (act == NULL)
+ return 0;
+
/* just loop through all F-Curves */
for (fcu= act->curves.first; fcu; fcu= fcu->next) {
if (ANIM_fcurve_keys_bezier_loop(bed, fcu, bezt_ok, bezt_cb, fcu_cb))
@@ -154,6 +162,10 @@ static short act_keys_bezier_loop(BeztEditData *bed, bAction *act, BeztEditFunc
/* This function is used to loop over the keyframe data of an AnimData block */
static short adt_keys_bezier_loop(BeztEditData *bed, AnimData *adt, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
{
+ /* sanity check */
+ if (adt == NULL)
+ return 0;
+
/* drivers or actions? */
if (filterflag & ADS_FILTER_ONLYDRIVERS) {
FCurve *fcu;
@@ -178,6 +190,10 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez
{
Key *key= ob_get_key(ob);
+ /* sanity check */
+ if (ob == NULL)
+ return 0;
+
/* firstly, Object's own AnimData */
if (ob->adt)
adt_keys_bezier_loop(bed, ob->adt, bezt_ok, bezt_cb, fcu_cb, filterflag);
@@ -194,7 +210,11 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez
/* This function is used to loop over the keyframe data in a Scene */
static short scene_keys_bezier_loop(BeztEditData *bed, Scene *sce, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag)
{
- World *wo= sce->world;
+ World *wo= (sce) ? sce->world : NULL;
+
+ /* sanity check */
+ if (sce == NULL)
+ return 0;
/* Scene's own animation */
if (sce->adt)
@@ -231,7 +251,7 @@ short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, B
return act_keys_bezier_loop(bed, (bAction *)ale->data, bezt_ok, bezt_cb, fcu_cb);
case ALE_OB: /* object */
- return ob_keys_bezier_loop(bed, (Object *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag);
+ return ob_keys_bezier_loop(bed, (Object *)ale->key_data, bezt_ok, bezt_cb, fcu_cb, filterflag);
case ALE_SCE: /* scene */
return scene_keys_bezier_loop(bed, (Scene *)ale->data, bezt_ok, bezt_cb, fcu_cb, filterflag);
}
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index efc0a0b9a57..e44c7ff5603 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -75,8 +75,9 @@ typedef enum eAnimCont_Types {
ANIMCONT_SHAPEKEY, /* shapekey (Key) */
ANIMCONT_GPENCIL, /* grease pencil (screen) */
ANIMCONT_DOPESHEET, /* dopesheet (bDopesheet) */
- ANIMCONT_FCURVES, /* animation F-Curves (bDopesheet) */ // XXX
+ ANIMCONT_FCURVES, /* animation F-Curves (bDopesheet) */
ANIMCONT_DRIVERS, /* drivers (bDopesheet) */
+ ANIMCONT_NLA, /* nla (bDopesheet) */
} eAnimCont_Types;
/* --------------- Channels -------------------- */
@@ -92,10 +93,10 @@ typedef struct bAnimListElem {
int flag; /* copy of elem's flags for quick access */
int index; /* copy of adrcode where applicable */
- void *key_data; /* motion data - ipo or ipo-curve */
+ void *key_data; /* motion data - mostly F-Curves, but can be other types too */
short datatype; /* type of motion data to expect */
- struct ID *id; /* ID block that channel is attached to (may be used */
+ struct ID *id; /* ID block that channel is attached to (may be used */
void *owner; /* group or channel which acts as this channel's owner */
short ownertype; /* type of owner */
@@ -106,6 +107,7 @@ typedef struct bAnimListElem {
// XXX was ACTTYPE_*
typedef enum eAnim_ChannelType {
ANIMTYPE_NONE= 0,
+ ANIMTYPE_ANIMDATA,
ANIMTYPE_SPECIALDATA,
ANIMTYPE_SCENE,
@@ -128,6 +130,9 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_GPDATABLOCK,
ANIMTYPE_GPLAYER,
+
+ ANIMTYPE_NLATRACK,
+ ANIMTYPE_NLAACTION,
} eAnim_ChannelType;
/* types of keyframe data in bAnimListElem */
@@ -135,6 +140,7 @@ typedef enum eAnim_KeyType {
ALE_NONE = 0, /* no keyframe data */
ALE_FCURVE, /* F-Curve */
ALE_GPFRAME, /* Grease Pencil Frames */
+ ALE_NLASTRIP, /* NLA Strips */
// XXX the following are for summaries... should these be kept?
ALE_SCE, /* Scene summary */
@@ -156,7 +162,9 @@ typedef enum eAnimFilter_Flags {
ANIMFILTER_CHANNELS = (1<<5), /* make list for interface drawing */
ANIMFILTER_ACTGROUPED = (1<<6), /* belongs to the active actiongroup */
ANIMFILTER_CURVEVISIBLE = (1<<7), /* F-Curve is visible for editing/viewing in Graph Editor */
- ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */ // FIXME: this is only relevant for F-Curves for now
+ ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */
+ ANIMFILTER_ANIMDATA = (1<<9), /* only return the underlying AnimData blocks (not the tracks, etc.) data comes from */
+ ANIMFILTER_NLATRACKS = (1<<10), /* only include NLA-tracks */
} eAnimFilter_Flags;
@@ -202,6 +210,10 @@ typedef enum eAnimFilter_Flags {
#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED)==0)
#define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT))
+/* NLA only */
+#define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED)
+#define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED)==0)
+
/* -------------- Channel Defines -------------- */
/* channel heights */
@@ -245,7 +257,7 @@ short ANIM_animdata_context_getdata(bAnimContext *ac);
void ANIM_deselect_anim_channels(void *data, short datatype, short test, short sel);
/* Set the 'active' channel of type channel_type, in the given action */
-void ANIM_set_active_channel(void *data, short datatype, int filter, void *channel_data, short channel_type);
+void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type);
/* --------------- Settings and/or Defines -------------- */
@@ -299,6 +311,8 @@ void ipo_rainbow(int cur, int tot, float *out);
/* ------------- NLA-Mapping ----------------------- */
/* anim_draw.c */
+// XXX these are soon to be depreceated?
+
/* Obtain the Object providing NLA-scaling for the given channel if applicable */
struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale);
@@ -308,10 +322,35 @@ void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct Object *ob, short re
/* Apply/Unapply NLA mapping to all keyframes in the nominated IPO block */
void ANIM_nla_mapping_apply_fcurve(struct Object *ob, struct FCurve *fcu, short restore, short only_keys);
-/* ------------- xxx macros ----------------------- */
+/* ------------- Utility macros ----------------------- */
+/* checks if the given BezTriple is selected */
#define BEZSELECTED(bezt) ((bezt->f2 & SELECT) || (bezt->f1 & SELECT) || (bezt->f3 & SELECT))
+/* set/clear/toggle macro
+ * - channel - channel with a 'flag' member that we're setting
+ * - smode - 0=clear, 1=set, 2=toggle
+ * - sflag - bitflag to set
+ */
+#define ACHANNEL_SET_FLAG(channel, smode, sflag) \
+ { \
+ if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \
+ else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag |= (sflag); \
+ else (channel)->flag &= ~(sflag); \
+ }
+
+/* set/clear/toggle macro, where the flag is negative
+ * - channel - channel with a 'flag' member that we're setting
+ * - smode - 0=clear, 1=set, 2=toggle
+ * - sflag - bitflag to set
+ */
+#define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \
+ { \
+ if (smode == ACHANNEL_SETFLAG_TOGGLE) (channel)->flag ^= (sflag); \
+ else if (smode == ACHANNEL_SETFLAG_ADD) (channel)->flag &= ~(sflag); \
+ else (channel)->flag |= (sflag); \
+ }
+
/* --------- anim_deps.c, animation updates -------- */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index ef682c871bc..c104f2034e8 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -118,6 +118,7 @@ int ED_operator_node_active(struct bContext *C);
int ED_operator_ipo_active(struct bContext *C);
int ED_operator_sequencer_active(struct bContext *C);
int ED_operator_image_active(struct bContext *C);
+int ED_operator_nla_active(struct bContext *C);
int ED_operator_logic_active(struct bContext *C);
int ED_operator_object_active(struct bContext *C);
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 4813b695795..50283113b62 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -52,6 +52,8 @@ enum {
V2D_COMMONVIEW_STANDARD,
/* listview (i.e. Outliner) */
V2D_COMMONVIEW_LIST,
+ /* stackview (this is basically a list where new items are added at the top) */
+ V2D_COMMONVIEW_STACK,
/* headers (this is basically the same as listview, but no y-panning) */
V2D_COMMONVIEW_HEADER,
/* ui region containing panels */
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 0a65718b708..af68c5e6b25 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -505,7 +505,10 @@ void ui_theme_init_userdef(void)
btheme->tact= btheme->tipo;
SETCOL(btheme->tact.strip, 12, 10, 10, 128);
SETCOL(btheme->tact.strip_select, 255, 140, 0, 255);
-
+
+ /* space nla */
+ btheme->tnla= btheme->tact;
+
/* space file */
/* to have something initialized */
btheme->tfile= btheme->tv3d;
@@ -522,20 +525,6 @@ void ui_theme_init_userdef(void)
SETCOL(btheme->tfile.scene, 250, 250, 250, 255);
-
-
- /* space nla */
- btheme->tnla= btheme->tv3d;
- SETCOL(btheme->tnla.back, 116, 116, 116, 255);
- SETCOL(btheme->tnla.text, 0, 0, 0, 255);
- SETCOL(btheme->tnla.text_hi, 255, 255, 255, 255);
- SETCOL(btheme->tnla.grid, 94, 94, 94, 255);
- SETCOL(btheme->tnla.shade1, 172, 172, 172, 255); // sliders
- SETCOL(btheme->tnla.shade2, 84, 44, 31, 100); // bar
- SETCOL(btheme->tnla.hilite, 17, 27, 60, 100); // bar
- SETCOL(btheme->tnla.strip_select, 0xff, 0xff, 0xaa, 255);
- SETCOL(btheme->tnla.strip, 0xe4, 0x9c, 0xc6, 255);
-
/* space seq */
btheme->tseq= btheme->tv3d;
SETCOL(btheme->tseq.back, 116, 116, 116, 255);
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 4621be6eda0..aa1cc5790ef 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -207,6 +207,23 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
}
break;
+ /* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead.
+ * zoom, aspect ratio, and alignment restrictions are set here */
+ case V2D_COMMONVIEW_STACK:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPZOOM|V2D_KEEPASPECT);
+ v2d->minzoom= v2d->maxzoom= 1.0f;
+
+ /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed= 1;
+
+ /* scroller settings are currently not set here... that is left for regions... */
+ }
+ break;
+
/* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
case V2D_COMMONVIEW_HEADER:
{
@@ -245,14 +262,14 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
v2d->tot.xmin= 0.0f;
v2d->tot.xmax= winx;
-
+
v2d->tot.ymax= 0.0f;
v2d->tot.ymin= -winy;
-
+
v2d->cur= v2d->tot;
}
break;
-
+
/* other view types are completely defined using their own settings already */
default:
/* we don't do anything here, as settings should be fine, but just make sure that rect */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 2aa6758850e..14121ccdc4d 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -164,6 +164,7 @@ int ED_operator_node_active(bContext *C)
return 0;
}
+// XXX rename
int ED_operator_ipo_active(bContext *C)
{
return ed_spacetype_test(C, SPACE_IPO);
@@ -179,6 +180,11 @@ int ED_operator_image_active(bContext *C)
return ed_spacetype_test(C, SPACE_IMAGE);
}
+int ED_operator_nla_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_NLA);
+}
+
int ED_operator_logic_active(bContext *C)
{
return ed_spacetype_test(C, SPACE_LOGIC);
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index b82e44f3aa3..6bfdf77e2e7 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -174,7 +174,7 @@ static int actkeys_deselectall_exec(bContext *C, wmOperator *op)
deselect_action_keys(&ac, 1, SELECT_ADD);
/* set notifier that things have changed */
- ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
return OPERATOR_FINISHED;
}
@@ -766,6 +766,7 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
if (ale == NULL) {
/* channel not found */
printf("Error: animation channel (index = %d) not found in mouse_action_keys() \n", channel_index);
+ BLI_freelistN(&anim_data);
return;
}
else {
@@ -857,17 +858,19 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
/* Highlight Action-Group or F-Curve? */
- if (ale->type == ANIMTYPE_GROUP) {
- bActionGroup *agrp= ale->data;
-
- agrp->flag |= AGRP_SELECTED;
- ANIM_set_active_channel(ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
- }
- else if (ale->type == ANIMTYPE_FCURVE) {
- FCurve *fcu= ale->data;
-
- fcu->flag |= FCURVE_SELECTED;
- ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ if (ale && ale->data) {
+ if (ale->type == ANIMTYPE_GROUP) {
+ bActionGroup *agrp= ale->data;
+
+ agrp->flag |= AGRP_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+ }
+ else if (ale->type == ANIMTYPE_FCURVE) {
+ FCurve *fcu= ale->data;
+
+ fcu->flag |= FCURVE_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ }
}
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
@@ -880,7 +883,7 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
}
/* only select keyframes if we clicked on a valid channel and hit something */
- if (ale) {
+ if (ale && found) {
/* apply selection to keyframes */
if (/*gpl*/0) {
/* grease pencil */
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index d57fc7f90bc..4c2def72de0 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -131,6 +131,9 @@ int ED_fileselect_layout_offset(FileLayout* layout, int x, int y)
int offsetx, offsety;
int active_file;
+ if (layout == NULL)
+ return NULL;
+
offsetx = (x)/(layout->tile_w + 2*layout->tile_border_x);
offsety = (y)/(layout->tile_h + 2*layout->tile_border_y);
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index a4babaad74c..5b00205b5d0 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -405,7 +405,7 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm
{
FMod_Generator *data= (FMod_Generator *)fcm->data;
char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1|Built-In Function%x2|Expression%x3";
- char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4";
+ char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4|Normalised Sin%x5";
int cy= *yco - 30;
uiBut *but;
@@ -555,6 +555,9 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm
case FCM_GENERATOR_FN_SQRT: /* square root */
sprintf(func_name, "sqrt(");
break;
+ case FCM_GENERATOR_FN_SINC: /* normalised sine wave */
+ sprintf(func_name, "sinc(");
+ break;
default: /* unknown */
sprintf(func_name, "<fn?>(");
break;
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 9aaef9fca8a..a222109b0fe 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -722,7 +722,7 @@ static void mouse_graph_keys (bAnimContext *ac, int mval[], short select_mode, s
/* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
if (fcu->flag & FCURVE_SELECTED) {
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
- ANIM_set_active_channel(ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
}
}
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 74002f64187..ef42b009bd4 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -192,7 +192,7 @@ static SpaceLink *graph_duplicate(SpaceLink *sl)
SpaceIpo *sipon= MEM_dupallocN(sl);
/* clear or remove stuff from old */
- //sipon->ipokey.first= sipon->ipokey.last= NULL;
+ BLI_duplicatelist(&sipon->ghostCurves, &((SpaceIpo *)sl)->ghostCurves);
sipon->ads= MEM_dupallocN(sipon->ads);
return (SpaceLink *)sipon;
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
new file mode 100644
index 00000000000..cb76f7fc735
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -0,0 +1,399 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+
+#include "BKE_animsys.h"
+#include "BKE_nla.h"
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "nla_intern.h" // own include
+
+
+/* ******************* nla editor space & buttons ************** */
+
+#define B_NOP 1
+#define B_REDR 2
+
+/* -------------- */
+
+static void do_nla_region_buttons(bContext *C, void *arg, int event)
+{
+ //Scene *scene= CTX_data_scene(C);
+
+ switch(event) {
+
+ }
+
+ /* default for now */
+ WM_event_add_notifier(C, NC_SCENE|NC_OBJECT|ND_TRANSFORM, NULL);
+}
+
+static int nla_panel_context(const bContext *C, PointerRNA *nlt_ptr, PointerRNA *strip_ptr)
+{
+ bAnimContext ac;
+ bAnimListElem *ale= NULL;
+ ListBase anim_data = {NULL, NULL};
+ short found=0;
+ int filter;
+
+ /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools)
+ * to work correctly is able to be correctly retrieved. There's no point showing empty panels?
+ */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return 0;
+
+ /* extract list of active channel(s), of which we should only take the first one (expecting it to be an NLA track) */
+ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_ACTIVE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+
+ /* found it, now set the pointers */
+ if (nlt_ptr) {
+ /* NLA-Track pointer */
+ RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr);
+ }
+ if (strip_ptr) {
+ /* NLA-Strip pointer */
+ NlaStrip *strip= BKE_nlastrip_find_active(nlt);
+ RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
+ }
+
+ found= 1;
+ break;
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ return found;
+}
+
+#if 0
+static int nla_panel_poll(const bContext *C, PanelType *pt)
+{
+ return nla_panel_context(C, NULL, NULL);
+}
+#endif
+
+static int nla_track_panel_poll(const bContext *C, PanelType *pt)
+{
+ PointerRNA ptr;
+ return (nla_panel_context(C, &ptr, NULL) && (ptr.data != NULL));
+}
+
+static int nla_strip_panel_poll(const bContext *C, PanelType *pt)
+{
+ PointerRNA ptr;
+ return (nla_panel_context(C, NULL, &ptr) && (ptr.data != NULL));
+}
+
+static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *pt)
+{
+ PointerRNA ptr;
+ NlaStrip *strip;
+
+ if (!nla_panel_context(C, NULL, &ptr))
+ return 0;
+ if (ptr.data == NULL)
+ return 0;
+
+ strip= ptr.data;
+ return (strip->type == NLASTRIP_TYPE_CLIP);
+}
+
+/* -------------- */
+
+/* active NLA-Track */
+static void nla_panel_track (const bContext *C, Panel *pa)
+{
+ PointerRNA nlt_ptr;
+ uiLayout *layout= pa->layout;
+ uiLayout *row;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, &nlt_ptr, NULL))
+ return;
+
+ block= uiLayoutGetBlock(layout);
+ uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+
+ /* Info - Active NLA-Context:Track ---------------------- */
+ row= uiLayoutRow(layout, 1);
+ uiItemR(row, NULL, ICON_NLA, &nlt_ptr, "name", 0, 0, 0);
+}
+
+/* generic settings for active NLA-Strip */
+static void nla_panel_properties(const bContext *C, Panel *pa)
+{
+ PointerRNA strip_ptr;
+ uiLayout *layout= pa->layout;
+ uiLayout *column, *row, *subcol;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, &strip_ptr))
+ return;
+
+ block= uiLayoutGetBlock(layout);
+ uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+
+ /* Strip Properties ------------------------------------- */
+ /* strip type */
+ row= uiLayoutRow(layout, 1);
+ uiItemR(row, NULL, 0, &strip_ptr, "type", 0, 0, 0);
+
+ /* strip extents */
+ column= uiLayoutColumn(layout, 1);
+ uiItemL(column, "Strip Extents:", 0);
+ uiItemR(column, NULL, 0, &strip_ptr, "start_frame", 0, 0, 0);
+ uiItemR(column, NULL, 0, &strip_ptr, "end_frame", 0, 0, 0);
+
+ /* extrapolation */
+ row= uiLayoutRow(layout, 1);
+ uiItemR(row, NULL, 0, &strip_ptr, "extrapolation", 0, 0, 0);
+
+ /* blending */
+ row= uiLayoutRow(layout, 1);
+ uiItemR(row, NULL, 0, &strip_ptr, "blending", 0, 0, 0);
+
+ /* blend in/out + autoblending
+ * - blend in/out can only be set when autoblending is off
+ */
+ column= uiLayoutColumn(layout, 1);
+ uiItemR(column, NULL, 0, &strip_ptr, "auto_blending", 0, 0, 0); // XXX as toggle?
+ subcol= uiLayoutColumn(column, 1);
+ uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "auto_blending")==0);
+ uiItemR(subcol, NULL, 0, &strip_ptr, "blend_in", 0, 0, 0);
+ uiItemR(subcol, NULL, 0, &strip_ptr, "blend_out", 0, 0, 0);
+
+ /* settings */
+ column= uiLayoutColumn(layout, 1);
+ uiItemL(column, "Playback Settings:", 0);
+ uiItemR(column, NULL, 0, &strip_ptr, "muted", 0, 0, 0);
+ uiItemR(column, NULL, 0, &strip_ptr, "reversed", 0, 0, 0);
+}
+
+
+/* action-clip only settings for active NLA-Strip */
+static void nla_panel_actclip(const bContext *C, Panel *pa)
+{
+ PointerRNA strip_ptr;
+ uiLayout *layout= pa->layout;
+ uiLayout *column, *row;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, &strip_ptr))
+ return;
+
+ // XXX FIXME: move this check into a poll callback
+ if (RNA_enum_get(&strip_ptr, "type") != NLASTRIP_TYPE_CLIP)
+ return;
+
+ block= uiLayoutGetBlock(layout);
+ uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+
+ /* Strip Properties ------------------------------------- */
+ /* action pointer */
+ row= uiLayoutRow(layout, 1);
+ uiItemR(row, NULL, ICON_ACTION, &strip_ptr, "action", 0, 0, 0);
+
+ /* action extents */
+ // XXX custom names were used here... probably not necessary in future?
+ column= uiLayoutColumn(layout, 1);
+ uiItemL(column, "Action Extents:", 0);
+ uiItemR(column, "Start Frame", 0, &strip_ptr, "action_start_frame", 0, 0, 0);
+ uiItemR(column, "End Frame", 0, &strip_ptr, "action_end_frame", 0, 0, 0);
+
+ /* action usage */
+ column= uiLayoutColumn(layout, 1);
+ uiItemL(column, "Playback Settings:", 0);
+ uiItemR(column, NULL, 0, &strip_ptr, "scale", 0, 0, 0);
+ uiItemR(column, NULL, 0, &strip_ptr, "repeat", 0, 0, 0);
+}
+
+/* evaluation settings for active NLA-Strip */
+static void nla_panel_evaluation(const bContext *C, Panel *pa)
+{
+ PointerRNA strip_ptr;
+ uiLayout *layout= pa->layout;
+ //uiLayout *column, *row, *subcol;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, &strip_ptr))
+ return;
+
+ block= uiLayoutGetBlock(layout);
+ uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+
+ // influence
+ // strip_time
+ // animated_influence
+ // animated_time
+}
+
+/* F-Modifiers for active NLA-Strip */
+static void nla_panel_modifiers(const bContext *C, Panel *pa)
+{
+ PointerRNA strip_ptr;
+ uiLayout *layout= pa->layout;
+ //uiLayout *column, *row, *subcol;
+ uiBlock *block;
+
+ /* check context and also validity of pointer */
+ if (!nla_panel_context(C, NULL, &strip_ptr))
+ return;
+
+ block= uiLayoutGetBlock(layout);
+ uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+
+ // TODO...
+}
+
+/* ******************* general ******************************** */
+
+
+void nla_buttons_register(ARegionType *art)
+{
+ PanelType *pt;
+
+ pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
+ strcpy(pt->idname, "NLA_PT_track");
+ strcpy(pt->label, "Active Track");
+ pt->draw= nla_panel_track;
+ pt->poll= nla_track_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
+ strcpy(pt->idname, "NLA_PT_properties");
+ strcpy(pt->label, "Active Strip");
+ pt->draw= nla_panel_properties;
+ pt->poll= nla_strip_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
+ strcpy(pt->idname, "NLA_PT_actionclip");
+ strcpy(pt->label, "Action Clip");
+ pt->draw= nla_panel_actclip;
+ pt->poll= nla_strip_actclip_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
+ strcpy(pt->idname, "NLA_PT_evaluation");
+ strcpy(pt->label, "Evaluation");
+ pt->draw= nla_panel_evaluation;
+ pt->poll= nla_strip_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
+ pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
+ strcpy(pt->idname, "NLA_PT_modifiers");
+ strcpy(pt->label, "Modifiers");
+ pt->draw= nla_panel_modifiers;
+ pt->poll= nla_strip_panel_poll;
+ BLI_addtail(&art->paneltypes, pt);
+}
+
+static int nla_properties(bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= nla_has_buttons_region(sa);
+
+ if(ar) {
+ ar->flag ^= RGN_FLAG_HIDDEN;
+ ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_properties(wmOperatorType *ot)
+{
+ ot->name= "Properties";
+ ot->idname= "NLAEDIT_OT_properties";
+
+ ot->exec= nla_properties;
+ ot->poll= ED_operator_nla_active;
+
+ /* flags */
+ ot->flag= 0;
+}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
new file mode 100644
index 00000000000..f928daa523b
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -0,0 +1,424 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung (major recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "DNA_listBase.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_animsys.h"
+#include "BKE_nla.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframes_edit.h"
+#include "ED_markers.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "nla_intern.h" // own include
+
+/* *********************************************** */
+/* Operators for NLA channels-list which need to be different from the standard Animation Editor ones */
+
+/* ******************** Mouse-Click Operator *********************** */
+/* Depending on the channel that was clicked on, the mouse click will activate whichever
+ * part of the channel is relevant.
+ *
+ * NOTE: eventually, this should probably be phased out when many of these things are replaced with buttons
+ */
+
+static void mouse_nla_channels (bAnimContext *ac, float x, int channel_index, short selectmode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get the channel that was clicked on */
+ /* filter channels */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ filter= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get channel from index */
+ ale= BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index);
+
+ BLI_freelistN(&anim_data);
+ return;
+ }
+
+ /* action to take depends on what channel we've got */
+ switch (ale->type) {
+ case ANIMTYPE_SCENE:
+ {
+ Scene *sce= (Scene *)ale->data;
+
+ if (x < 16) {
+ /* toggle expand */
+ sce->flag ^= SCE_DS_COLLAPSED;
+ }
+ else {
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ sce->flag ^= SCE_DS_SELECTED;
+ }
+ else {
+ sce->flag |= SCE_DS_SELECTED;
+ }
+ }
+ }
+ break;
+ case ANIMTYPE_OBJECT:
+ {
+ bDopeSheet *ads= (bDopeSheet *)ac->data;
+ Scene *sce= (Scene *)ads->source;
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ if (x < 16) {
+ /* toggle expand */
+ ob->nlaflag ^= OB_ADS_COLLAPSED; // XXX
+ }
+ else {
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ base->flag ^= SELECT;
+ ob->flag= base->flag;
+ }
+ else {
+ Base *b;
+
+ /* deleselect all */
+ for (b= sce->base.first; b; b= b->next) {
+ b->flag &= ~SELECT;
+ b->object->flag= b->flag;
+ }
+
+ /* select object now */
+ base->flag |= SELECT;
+ ob->flag |= SELECT;
+ }
+
+ /* xxx should be ED_base_object_activate(), but we need context pointer for that... */
+ //set_active_base(base);
+ }
+ }
+ break;
+ case ANIMTYPE_FILLMATD:
+ {
+ Object *ob= (Object *)ale->data;
+ ob->nlaflag ^= OB_ADS_SHOWMATS; // XXX
+ }
+ break;
+
+ case ANIMTYPE_DSMAT:
+ {
+ Material *ma= (Material *)ale->data;
+ ma->flag ^= MA_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSLAM:
+ {
+ Lamp *la= (Lamp *)ale->data;
+ la->flag ^= LA_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSCAM:
+ {
+ Camera *ca= (Camera *)ale->data;
+ ca->flag ^= CAM_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSCUR:
+ {
+ Curve *cu= (Curve *)ale->data;
+ cu->flag ^= CU_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSSKEY:
+ {
+ Key *key= (Key *)ale->data;
+ key->flag ^= KEYBLOCK_DS_EXPAND;
+ }
+ break;
+ case ANIMTYPE_DSWOR:
+ {
+ World *wo= (World *)ale->data;
+ wo->flag ^= WO_DS_EXPAND;
+ }
+ break;
+
+ case ANIMTYPE_NLATRACK:
+ {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+ short offset;
+
+ /* offset for start of channel (on LHS of channel-list) */
+ if (ale->id) {
+ /* special exception for materials */
+ if (GS(ale->id->name) == ID_MA)
+ offset= 21 + NLACHANNEL_BUTTON_WIDTH;
+ else
+ offset= 14;
+ }
+ else
+ offset= 0;
+
+ if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) {
+ /* toggle protection (only if there's a toggle there) */
+ nlt->flag ^= NLATRACK_PROTECTED;
+ }
+ else if (x >= (NLACHANNEL_NAMEWIDTH-2*NLACHANNEL_BUTTON_WIDTH)) {
+ /* toggle mute */
+ nlt->flag ^= NLATRACK_MUTED;
+ }
+ else if (x <= ((NLACHANNEL_BUTTON_WIDTH*2)+offset)) {
+ /* toggle 'solo' */
+ BKE_nlatrack_solo_toggle(adt, nlt);
+ }
+ else {
+ /* set selection */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this F-Curve only */
+ nlt->flag ^= NLATRACK_SELECTED;
+ }
+ else {
+ /* select F-Curve by itself */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ nlt->flag |= NLATRACK_SELECTED;
+ }
+
+ /* if NLA-Track is selected now, make NLA-Track the 'active' one in the visible list */
+ if (nlt->flag & NLATRACK_SELECTED)
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
+ }
+ }
+ break;
+ case ANIMTYPE_NLAACTION:
+ {
+ AnimData *adt= BKE_animdata_from_id(ale->owner); /* this won't crash, right? */
+
+ /* for now, only do something if user clicks on the 'push-down' button */
+ if (x >= (NLACHANNEL_NAMEWIDTH-NLACHANNEL_BUTTON_WIDTH)) {
+ /* activate push-down function */
+ // TODO: make this use the operator instead of calling the function directly
+ // however, calling the operator requires that we supply the args, and that works with proper buttons only
+ BKE_nla_action_pushdown(adt);
+ }
+ }
+ break;
+
+ default:
+ printf("Error: Invalid channel type in mouse_nla_channels() \n");
+ }
+
+ /* free channels */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+/* handle clicking */
+static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ bAnimContext ac;
+ Scene *scene;
+ ARegion *ar;
+ View2D *v2d;
+ int mval[2], channel_index;
+ short selectmode;
+ float x, y;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get useful pointers from animation context data */
+ scene= ac.scene;
+ ar= ac.ar;
+ v2d= &ar->v2d;
+
+ /* get mouse coordinates (in region coordinates) */
+ mval[0]= (event->x - ar->winrct.xmin);
+ mval[1]= (event->y - ar->winrct.ymin);
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode= SELECT_INVERT;
+ else
+ selectmode= SELECT_REPLACE;
+
+ /* figure out which channel user clicked in
+ * Note: although channels technically start at y= NLACHANNEL_FIRST, we need to adjust by half a channel's height
+ * so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use
+ * NLACHANNEL_HEIGHT_HALF.
+ */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+ UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP, 0, (float)NLACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
+
+ /* handle mouse-click in the relevant channel then */
+ mouse_nla_channels(&ac, x, channel_index, selectmode);
+
+ /* set notifier tha things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_CHANNELS);
+
+ return OPERATOR_FINISHED;
+}
+
+void NLA_OT_channels_click (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mouse Click on Channels";
+ ot->idname= "NLA_OT_channels_click";
+
+ /* api callbacks */
+ ot->invoke= nlachannels_mouseclick_invoke;
+ ot->poll= nlaop_poll_tweakmode_off; // xxx?
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
+}
+
+/* *********************************************** */
+/* Special Operators */
+
+/* ******************** Add Tracks Operator ***************************** */
+/* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */
+
+static int nlaedit_add_tracks_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ AnimData *lastAdt = NULL;
+ short above_sel= RNA_boolean_get(op->ptr, "above_selected");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the AnimData blocks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_SEL);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* add tracks... */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+
+ /* check if just adding a new track above this one,
+ * or whether we're adding a new one to the top of the stack that this one belongs to
+ */
+ if (above_sel) {
+ /* just add a new one above this one */
+ add_nlatrack(adt, nlt);
+ }
+ else if ((lastAdt == NULL) || (adt != lastAdt)) {
+ /* add one track to the top of the owning AnimData's stack, then don't add anymore to this stack */
+ add_nlatrack(adt, NULL);
+ lastAdt= adt;
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void NLA_OT_add_tracks (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Track(s)";
+ ot->idname= "NLA_OT_add_tracks";
+ ot->description= "Add NLA-Tracks above/after the selected tracks.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_add_tracks_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "above_selected", 0, "Above Selected", "Add a new NLA Track above every existing selected one.");
+}
+
+/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
new file mode 100644
index 00000000000..9a9cbeeff21
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -0,0 +1,793 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung (major recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_listBase.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+#include "DNA_vec_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_animsys.h"
+#include "BKE_nla.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "ED_markers.h"
+
+#include "nla_intern.h" // own include
+
+/* XXX */
+extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
+extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
+
+/* *********************************************** */
+/* Strips */
+
+static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3])
+{
+ if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) {
+ /* active strip should be drawn green when it is acting as the tweaking strip.
+ * however, this case should be skipped for when not in EditMode...
+ */
+ // FIXME: hardcoded temp-hack colors
+ color[0]= 0.3f;
+ color[1]= 0.95f;
+ color[2]= 0.1f;
+ }
+ else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) {
+ /* alert user that this strip is also used by the tweaking track (this is set when going into
+ * 'editmode' for that strip), since the edits made here may not be what the user anticipated
+ */
+ // FIXME: hardcoded temp-hack colors
+ color[0]= 0.85f;
+ color[1]= 0.0f;
+ color[2]= 0.0f;
+ }
+ else if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* selected strip - use theme color for selected */
+ UI_GetThemeColor3fv(TH_STRIP_SELECT, color);
+ }
+ else {
+ /* normal, unselected strip - use standard strip theme color */
+ UI_GetThemeColor3fv(TH_STRIP, color);
+ }
+}
+
+static void nla_draw_strip (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
+{
+ float color[3];
+
+ /* get color of strip */
+ nla_strip_get_color_inside(adt, strip, color);
+
+ /* draw extrapolation info first (as backdrop) */
+ if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
+ /* enable transparency... */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ switch (strip->extendmode) {
+ /* since this does both sides, only do the 'before' side, and leave the rest to the next case */
+ case NLASTRIP_EXTEND_HOLD:
+ /* only need to draw here if there's no strip before since
+ * it only applies in such a situation
+ */
+ if (strip->prev == NULL) {
+ /* set the drawing color to the color of the strip, but with very faint alpha */
+ glColor4f(color[0], color[1], color[2], 0.15f);
+
+ /* draw the rect to the edge of the screen */
+ glBegin(GL_QUADS);
+ glVertex2f(v2d->cur.xmin, yminc);
+ glVertex2f(v2d->cur.xmin, ymaxc);
+ glVertex2f(strip->start, ymaxc);
+ glVertex2f(strip->start, yminc);
+ glEnd();
+ }
+ /* no break needed... */
+
+ /* this only draws after the strip */
+ case NLASTRIP_EXTEND_HOLD_FORWARD:
+ /* only need to try and draw if the next strip doesn't occur immediately after */
+ if ((strip->next == NULL) || (IS_EQ(strip->next->start, strip->end)==0)) {
+ /* set the drawing color to the color of the strip, but this time less faint */
+ glColor4f(color[0], color[1], color[2], 0.3f);
+
+ /* draw the rect to the next strip or the edge of the screen */
+ glBegin(GL_QUADS);
+ glVertex2f(strip->end, yminc);
+ glVertex2f(strip->end, ymaxc);
+
+ if (strip->next) {
+ glVertex2f(strip->next->start, ymaxc);
+ glVertex2f(strip->next->start, yminc);
+ }
+ else {
+ glVertex2f(v2d->cur.xmax, ymaxc);
+ glVertex2f(v2d->cur.xmax, yminc);
+ }
+ glEnd();
+ }
+ break;
+ }
+
+ glDisable(GL_BLEND);
+ }
+
+ /* draw 'inside' of strip itself */
+ glColor3fv(color);
+ uiSetRoundBox(15); /* all corners rounded */
+ gl_round_box_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
+
+
+ /* draw strip outline
+ * - color used here is to indicate active vs non-active
+ */
+ if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
+ /* strip should appear 'sunken', so draw a light border around it */
+ glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors
+ }
+ else {
+ /* strip should appear to stand out, so draw a dark border around it */
+ glColor3f(0.0f, 0.0f, 0.0f);
+ }
+
+ /* - line style: dotted for muted */
+ if (strip->flag & NLASTRIP_FLAG_MUTED)
+ setlinestyle(4);
+
+ /* draw outline */
+ gl_round_box_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
+
+ /* reset linestyle */
+ setlinestyle(0);
+}
+
+/* add the relevant text to the cache of text-strings to draw in pixelspace */
+static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc)
+{
+ char str[256];
+ rctf rect;
+
+ /* for now, just init the string with fixed-formats */
+ switch (strip->type) {
+ case NLASTRIP_TYPE_TRANSITION: /* Transition */
+ sprintf(str, "%d | Transition | %.2f <-> %.2f", index, strip->start, strip->end);
+ break;
+
+ case NLASTRIP_TYPE_CLIP: /* Action-Clip (default) */
+ default:
+ if (strip->act)
+ sprintf(str, "%d | Act: %s | %.2f <-> %.2f", index, strip->act->id.name+2, strip->start, strip->end);
+ else
+ sprintf(str, "%d | Act: <NONE>", index); // xxx... need a better format?
+ break;
+ }
+
+ /* set text colour - if colours (see above) are light, draw black text, otherwise draw white */
+ if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER))
+ glColor3f(0.0f, 0.0f, 0.0f);
+ else
+ glColor3f(1.0f, 1.0f, 1.0f);
+
+ /* set bounding-box for text
+ * - padding of 2 'units' on either side
+ */
+ // TODO: make this centered?
+ rect.xmin= strip->start + 2;
+ rect.ymin= yminc;
+ rect.xmax= strip->end - 2;
+ rect.ymax= ymaxc;
+
+ /* add this string to the cache of texts to draw*/
+ UI_view2d_text_cache_rectf(v2d, &rect, str);
+}
+
+/* ---------------------- */
+
+void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ar->v2d;
+ float y= 0.0f;
+ int items, height;
+
+ /* build list of channels to draw */
+ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
+ items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Update max-extent of channels here (taking into account scrollers):
+ * - this is done to allow the channel list to be scrollable, but must be done here
+ * to avoid regenerating the list again and/or also because channels list is drawn first
+ * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
+ * start of list offset, and the second is as a correction for the scrollers.
+ */
+ height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2));
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin= (float)(-height);
+
+ /* loop through channels, and set up drawing depending on their type */
+ y= (float)(-NLACHANNEL_HEIGHT);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ /* data to draw depends on the type of channel */
+ switch (ale->type) {
+ case ANIMTYPE_NLATRACK:
+ {
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+ int index;
+
+ /* draw backdrop? */
+ // TODO...
+
+ /* draw each strip in the track (if visible) */
+ for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) {
+ if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
+ /* draw the visualisation of the strip */
+ nla_draw_strip(adt, nlt, strip, v2d, yminc, ymaxc);
+
+ /* add the text for this strip to the cache */
+ nla_draw_strip_text(nlt, strip, index, v2d, yminc, ymaxc);
+ }
+ }
+ }
+ break;
+
+ case ANIMTYPE_NLAACTION:
+ {
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+
+ /* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
+ * and a second darker rect within which we draw keyframe indicator dots if there's data
+ */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
+ // greenish color (same as tweaking strip) - hardcoded for now
+ glColor4f(0.3f, 0.95f, 0.1f, 0.3f); // FIXME: only draw the actual range of the action darker?
+ }
+ else {
+ if (ale->data)
+ glColor4f(0.8f, 0.2f, 0.0f, 0.4f); // reddish color - hardcoded for now
+ else
+ glColor4f(0.6f, 0.5f, 0.5f, 0.3f); // greyish-red color - hardcoded for now
+ }
+
+ /* draw slightly shifted up for greater separation from standard channels,
+ * but also slightly shorter for some more contrast when viewing the strips
+ */
+ glBegin(GL_QUADS);
+ glVertex2f(v2d->cur.xmin, yminc+NLACHANNEL_SKIP);
+ glVertex2f(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP);
+ glVertex2f(v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
+ glVertex2f(v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
+ glEnd();
+
+ glDisable(GL_BLEND);
+ }
+ break;
+ }
+ }
+
+ /* adjust y-position for next one */
+ y -= NLACHANNEL_STEP;
+ }
+
+ /* free tempolary channels */
+ BLI_freelistN(&anim_data);
+}
+
+/* *********************************************** */
+/* Channel List */
+
+void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ar->v2d;
+ float x= 0.0f, y= 0.0f;
+ int items, height;
+
+ /* build list of channels to draw */
+ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
+ items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* Update max-extent of channels here (taking into account scrollers):
+ * - this is done to allow the channel list to be scrollable, but must be done here
+ * to avoid regenerating the list again and/or also because channels list is drawn first
+ * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
+ * start of list offset, and the second is as a correction for the scrollers.
+ */
+ height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2));
+ /* don't use totrect set, as the width stays the same
+ * (NOTE: this is ok here, the configuration is pretty straightforward)
+ */
+ v2d->tot.ymin= (float)(-height);
+
+ /* loop through channels, and set up drawing depending on their type */
+ y= (float)(-NLACHANNEL_HEIGHT);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF);
+ const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF);
+ const float ydatac= (float)(y - 7);
+
+ /* check if visible */
+ if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
+ {
+ short indent= 0, offset= 0, sel= 0, group= 0;
+ int expand= -1, protect = -1, special= -1, mute = -1;
+ char name[128];
+
+ /* determine what needs to be drawn */
+ switch (ale->type) {
+ case ANIMTYPE_SCENE: /* scene */
+ {
+ Scene *sce= (Scene *)ale->data;
+
+ group= 4;
+ indent= 0;
+
+ special= ICON_SCENE_DATA;
+
+ /* only show expand if there are any channels */
+ if (EXPANDED_SCEC(sce))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_SCEC(sce);
+ strcpy(name, sce->id.name+2);
+ }
+ break;
+ case ANIMTYPE_OBJECT: /* object */
+ {
+ Base *base= (Base *)ale->data;
+ Object *ob= base->object;
+
+ group= 4;
+ indent= 0;
+
+ /* icon depends on object-type */
+ if (ob->type == OB_ARMATURE)
+ special= ICON_ARMATURE_DATA;
+ else
+ special= ICON_OBJECT_DATA;
+
+ /* only show expand if there are any channels */
+ if (EXPANDED_OBJC(ob))
+ expand= ICON_TRIA_DOWN;
+ else
+ expand= ICON_TRIA_RIGHT;
+
+ sel = SEL_OBJC(base);
+ strcpy(name, ob->id.name+2);
+ }
+ break;
+ case ANIMTYPE_FILLMATD: /* object materials (dopesheet) expand widget */
+ {
+ Object *ob = (Object *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_MATERIAL_DATA;
+
+ if (FILTER_MAT_OBJC(ob))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, "Materials");
+ }
+ break;
+
+
+ case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */
+ {
+ Material *ma = (Material *)ale->data;
+
+ group = 0;
+ indent = 0;
+ special = ICON_MATERIAL_DATA;
+ offset = 21;
+
+ if (FILTER_MAT_OBJD(ma))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, ma->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */
+ {
+ Lamp *la = (Lamp *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_LAMP_DATA;
+
+ if (FILTER_LAM_OBJD(la))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, la->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */
+ {
+ Camera *ca = (Camera *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CAMERA_DATA;
+
+ if (FILTER_CAM_OBJD(ca))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, ca->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */
+ {
+ Curve *cu = (Curve *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_CURVE_DATA;
+
+ if (FILTER_CUR_OBJD(cu))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, cu->id.name+2);
+ }
+ break;
+ case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */
+ {
+ Key *key= (Key *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_SHAPEKEY_DATA; // XXX
+
+ if (FILTER_SKE_OBJD(key))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ //sel = SEL_OBJC(base);
+ strcpy(name, "Shape Keys");
+ }
+ break;
+ case ANIMTYPE_DSWOR: /* world (dopesheet) expand widget */
+ {
+ World *wo= (World *)ale->data;
+
+ group = 4;
+ indent = 1;
+ special = ICON_WORLD_DATA;
+
+ if (FILTER_WOR_SCED(wo))
+ expand = ICON_TRIA_DOWN;
+ else
+ expand = ICON_TRIA_RIGHT;
+
+ strcpy(name, wo->id.name+2);
+ }
+ break;
+
+ case ANIMTYPE_NLATRACK: /* NLA Track */
+ {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+
+ indent= 0;
+
+ if (ale->id) {
+ /* special exception for materials */
+ if (GS(ale->id->name) == ID_MA) {
+ offset= 21;
+ indent= 1;
+ }
+ else
+ offset= 14;
+ }
+ else
+ offset= 0;
+
+ /* FIXME: 'solo' as the 'special' button?
+ * - need special icons for these
+ */
+ if (nlt->flag & NLATRACK_SOLO)
+ special= ICON_LAYER_ACTIVE;
+ else
+ special= ICON_LAYER_USED;
+
+ /* if this track is active and we're tweaking it, don't draw these toggles */
+ // TODO: need a special macro for this...
+ if ( ((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0 )
+ {
+ if (nlt->flag & NLATRACK_MUTED)
+ mute = ICON_MUTE_IPO_ON;
+ else
+ mute = ICON_MUTE_IPO_OFF;
+
+ if (EDITABLE_NLT(nlt))
+ protect = ICON_UNLOCKED;
+ else
+ protect = ICON_LOCKED;
+ }
+
+ sel = SEL_NLT(nlt);
+ strcpy(name, nlt->name);
+ }
+ break;
+ case ANIMTYPE_NLAACTION: /* NLA Action-Line */
+ {
+ bAction *act= (bAction *)ale->data;
+
+ group = 5;
+
+ if (ale->id) {
+ /* special exception for materials */
+ if (GS(ale->id->name) == ID_MA) {
+ offset= 21;
+ indent= 1;
+ }
+ else
+ offset= 14;
+ }
+ else
+ offset= 0;
+
+ special = ICON_ACTION;
+
+ if (act)
+ sprintf(name, "ActAction: <%s>", act->id.name+2);
+ else
+ sprintf(name, "<No Action>");
+ }
+ break;
+ }
+
+ /* now, start drawing based on this information */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* draw backing strip behind channel name */
+ if (group == 4) {
+ /* only used in dopesheet... */
+ if (ELEM(ale->type, ANIMTYPE_SCENE, ANIMTYPE_OBJECT)) {
+ /* object channel - darker */
+ UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
+ uiSetRoundBox((expand == ICON_TRIA_DOWN)? (8):(1|8));
+ gl_round_box(GL_POLYGON, x+offset, yminc, (float)NLACHANNEL_NAMEWIDTH, ymaxc, 10);
+ }
+ else {
+ /* sub-object folders - lighter */
+ UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
+
+ offset += 7 * indent;
+ glBegin(GL_QUADS);
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
+ glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
+ glEnd();
+
+ /* clear group value, otherwise we cause errors... */
+ group = 0;
+ }
+ }
+ else if (group == 5) {
+ /* Action Line */
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+
+ // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
+ // greenish color (same as tweaking strip) - hardcoded for now
+ glColor3f(0.3f, 0.95f, 0.1f);
+ }
+ else {
+ if (ale->data)
+ glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now
+ else
+ glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now
+ }
+
+ offset += 7 * indent;
+
+ /* only on top two corners, to show that this channel sits on top of the preceeding ones */
+ uiSetRoundBox((1|2));
+
+ /* draw slightly shifted up vertically to look like it has more separtion from other channels,
+ * but we then need to slightly shorten it so that it doesn't look like it overlaps
+ */
+ gl_round_box(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)NLACHANNEL_NAMEWIDTH, ymaxc+NLACHANNEL_SKIP-1, 8);
+
+ /* clear group value, otherwise we cause errors... */
+ group = 0;
+ }
+ else {
+ /* for normal channels
+ * - use 3 shades of color group/standard color for 3 indention level
+ */
+ UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
+
+ indent += group;
+ offset += 7 * indent;
+ glBegin(GL_QUADS);
+ glVertex2f(x+offset, yminc);
+ glVertex2f(x+offset, ymaxc);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH, ymaxc);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH, yminc);
+ glEnd();
+ }
+
+ /* draw expand/collapse triangle */
+ if (expand > 0) {
+ UI_icon_draw(x+offset, ydatac, expand);
+ offset += 17;
+ }
+
+ /* draw special icon indicating certain data-types */
+ if (special > -1) {
+ /* for normal channels */
+ UI_icon_draw(x+offset, ydatac, special);
+ offset += 17;
+ }
+ glDisable(GL_BLEND);
+
+ /* draw name */
+ if (sel)
+ UI_ThemeColor(TH_TEXT_HI);
+ else
+ UI_ThemeColor(TH_TEXT);
+ offset += 3;
+ UI_DrawString(x+offset, y-4, name);
+
+ /* reset offset - for RHS of panel */
+ offset = 0;
+
+ /* set blending again, as text drawing may clear it */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ /* draw protect 'lock' */
+ if (protect > -1) {
+ offset = 16;
+ UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, protect);
+ }
+
+ /* draw mute 'eye' */
+ if (mute > -1) {
+ offset += 16;
+ UI_icon_draw((float)(NLACHANNEL_NAMEWIDTH-offset), ydatac, mute);
+ }
+
+ /* draw NLA-action line 'status-icons' - only when there's an action */
+ if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+
+ offset += 16;
+
+ /* now draw some indicator icons */
+ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
+ /* 'tweaking action' - not a button */
+ UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_EDIT);
+ }
+ else {
+ /* XXX firstly draw a little rect to help identify that it's different from the toggles */
+ glBegin(GL_LINE_LOOP);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+9);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+9);
+ glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7);
+ glEnd(); // GL_LINES
+
+ /* 'push down' icon for normal active-actions */
+ UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE);
+ }
+ }
+
+ glDisable(GL_BLEND);
+ }
+
+ /* adjust y-position for next one */
+ y -= NLACHANNEL_STEP;
+ }
+
+ /* free tempolary channels */
+ BLI_freelistN(&anim_data);
+}
+
+/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
new file mode 100644
index 00000000000..8b7c6bb99c6
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -0,0 +1,699 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung (major recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_animsys.h"
+#include "BKE_nla.h"
+#include "BKE_context.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+
+#include "ED_anim_api.h"
+#include "ED_markers.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_transform.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "nla_intern.h" // own include
+
+/* *********************************************** */
+/* 'Special' Editing */
+
+/* ******************** Tweak-Mode Operators ***************************** */
+/* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited
+ * as if it were the normal Active-Action of its AnimData block.
+ */
+
+static int nlaedit_enable_tweakmode_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ int ok=0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the AnimData blocks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* if no blocks, popup error? */
+ if (anim_data.first == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for each AnimData block with NLA-data, try setting it in tweak-mode */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ AnimData *adt= ale->data;
+
+ /* try entering tweakmode if valid */
+ ok += BKE_nla_tweakmode_enter(adt);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* if we managed to enter tweakmode on at least one AnimData block,
+ * set the flag for this in the active scene and send notifiers
+ */
+ if (ac.scene && ok) {
+ /* set editing flag */
+ ac.scene->flag |= SCE_NLA_EDIT_ON;
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweakmode on.");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_tweakmode_enter (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Enter Tweak Mode";
+ ot->idname= "NLAEDIT_OT_tweakmode_enter";
+ ot->description= "Enter tweaking mode for the action referenced by the active strip.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_enable_tweakmode_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ------------- */
+
+static int nlaedit_disable_tweakmode_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the AnimData blocks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* if no blocks, popup error? */
+ if (anim_data.first == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for each AnimData block with NLA-data, try exitting tweak-mode */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ AnimData *adt= ale->data;
+
+ /* try entering tweakmode if valid */
+ BKE_nla_tweakmode_exit(adt);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* if we managed to enter tweakmode on at least one AnimData block,
+ * set the flag for this in the active scene and send notifiers
+ */
+ if (ac.scene) {
+ /* clear editing flag */
+ ac.scene->flag &= ~SCE_NLA_EDIT_ON;
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+ }
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_tweakmode_exit (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Exit Tweak Mode";
+ ot->idname= "NLAEDIT_OT_tweakmode_exit";
+ ot->description= "Exit tweaking mode for the action referenced by the active strip.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_disable_tweakmode_exec;
+ ot->poll= nlaop_poll_tweakmode_on;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* *********************************************** */
+/* NLA Editing Operations */
+
+/* ******************** Add Action-Clip Operator ***************************** */
+/* Add a new Action-Clip strip to the active track (or the active block if no space in the track) */
+
+/* pop up menu allowing user to choose the action to use */
+static int nlaedit_add_actionclip_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ Main *m= CTX_data_main(C);
+ bAction *act;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ pup= uiPupMenuBegin(C, "Add Action Clip", 0);
+ layout= uiPupMenuLayout(pup);
+
+ /* loop through Actions in Main database, adding as items in the menu */
+ for (act= m->action.first; act; act= act->id.next)
+ uiItemStringO(layout, act->id.name+2, 0, "NLAEDIT_OT_add_actionclip", "action", act->id.name);
+ uiItemS(layout);
+
+ uiPupMenuEnd(C, pup);
+
+ return OPERATOR_CANCELLED;
+}
+
+/* add the specified action as new strip */
+static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ Scene *scene;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter, items;
+
+ bAction *act = NULL;
+ char actname[22];
+ float cfra;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ scene= ac.scene;
+ cfra= (float)CFRA;
+
+ /* get action to use */
+ RNA_string_get(op->ptr, "action", actname);
+ act= (bAction *)find_id("AC", actname+2);
+
+ if (act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No valid Action to add.");
+ //printf("Add strip - actname = '%s' \n", actname);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get a list of the editable tracks being shown in the NLA
+ * - this is limited to active ones for now, but could be expanded to
+ */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
+ items= ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ if (items == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No active track(s) to add strip to.");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for every active track, try to add strip to free space in track or to the top of the stack if no space */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+ NlaStrip *strip= NULL;
+
+ /* create a new strip, and offset it to start on the current frame */
+ strip= add_nlastrip(act);
+
+ strip->end += (cfra - strip->start);
+ strip->start = cfra;
+
+ /* firstly try adding strip to our current track, but if that fails, add to a new track */
+ if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+ /* trying to add to the current failed (no space),
+ * so add a new track to the stack, and add to that...
+ */
+ nlt= add_nlatrack(adt, NULL);
+ BKE_nlatrack_add_strip(nlt, strip);
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_add_actionclip (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Action Strip";
+ ot->idname= "NLAEDIT_OT_add_actionclip";
+ ot->description= "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track.";
+
+ /* api callbacks */
+ ot->invoke= nlaedit_add_actionclip_invoke;
+ ot->exec= nlaedit_add_actionclip_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ // TODO: this would be nicer as an ID-pointer...
+ RNA_def_string(ot->srna, "action", "", 21, "Action", "Name of Action to add as a new Action-Clip Strip.");
+}
+
+/* ******************** Add Transition Operator ***************************** */
+/* Add a new transition strip between selected strips */
+
+/* add the specified action as new strip */
+static int nlaedit_add_transition_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ int done = 0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each track, find pairs of strips to add transitions to */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *s1, *s2;
+
+ /* get initial pair of strips */
+ if ELEM(nlt->strips.first, NULL, nlt->strips.last)
+ continue;
+ s1= nlt->strips.first;
+ s2= s1->next;
+
+ /* loop over strips */
+ for (; s1 && s2; s1=s2, s2=s2->next) {
+ NlaStrip *strip;
+
+ /* check if both are selected */
+ if ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT))
+ continue;
+ /* check if there's space between the two */
+ if (IS_EQ(s1->end, s2->start))
+ continue;
+
+ /* allocate new strip */
+ strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
+ BLI_insertlinkafter(&nlt->strips, s1, strip);
+
+ /* set the type */
+ strip->type= NLASTRIP_TYPE_TRANSITION;
+
+ /* generic settings
+ * - selected flag to highlight this to the user
+ * - auto-blends to ensure that blend in/out values are automatically
+ * determined by overlaps of strips
+ */
+ strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
+
+ /* range is simply defined as the endpoints of the adjacent strips */
+ strip->start = s1->end;
+ strip->end = s2->start;
+
+ /* scale and repeat aren't of any use, but shouldn't ever be 0 */
+ strip->scale= 1.0f;
+ strip->repeat = 1.0f;
+
+ /* make note of this */
+ done++;
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* was anything added? */
+ if (done) {
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Needs at least a pair of adjacent selected strips.");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void NLAEDIT_OT_add_transition (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Transition";
+ ot->idname= "NLAEDIT_OT_add_transition";
+ ot->description= "Add a transition strip between two adjacent selected strips.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_add_transition_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Duplicate Strips Operator ************************** */
+/* Duplicates the selected NLA-Strips, putting them on new tracks above the one
+ * the originals were housed in.
+ */
+
+static int nlaedit_duplicate_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ short done = 0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of editable tracks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* duplicate strips in tracks starting from the last one so that we're
+ * less likely to duplicate strips we just duplicated...
+ */
+ for (ale= anim_data.last; ale; ale= ale->prev) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ AnimData *adt= BKE_animdata_from_id(ale->id);
+ NlaStrip *strip, *nstrip, *next;
+ NlaTrack *track;
+
+ for (strip= nlt->strips.first; strip; strip= next) {
+ next= strip->next;
+
+ /* if selected, split the strip at its midpoint */
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* make a copy (assume that this is possible) */
+ nstrip= copy_nlastrip(strip);
+
+ /* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */
+ if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
+ /* need to add a new track above the one above the current one
+ * - if the current one is the last one, nlt->next will be NULL, which defaults to adding
+ * at the top of the stack anyway...
+ */
+ track= add_nlatrack(adt, nlt->next);
+ BKE_nlatrack_add_strip(track, nstrip);
+ }
+
+ /* deselect the original */
+ strip->flag &= ~NLASTRIP_FLAG_SELECT;
+
+ done++;
+ }
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ if (done) {
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else
+ return OPERATOR_CANCELLED;
+}
+
+static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ nlaedit_duplicate_exec(C, op);
+
+ RNA_int_set(op->ptr, "mode", TFM_TIME_TRANSLATE); // XXX
+ WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_duplicate (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate Strips";
+ ot->idname= "NLAEDIT_OT_duplicate";
+ ot->description= "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals.";
+
+ /* api callbacks */
+ ot->invoke= nlaedit_duplicate_invoke;
+ ot->exec= nlaedit_duplicate_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+/* ******************** Delete Strips Operator ***************************** */
+/* Deletes the selected NLA-Strips */
+
+static int nlaedit_delete_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, delete all selected strips */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip, *nstrip;
+
+ for (strip= nlt->strips.first; strip; strip= nstrip) {
+ nstrip= strip->next;
+
+ /* if selected, delete */
+ if (strip->flag & NLASTRIP_FLAG_SELECT)
+ free_nlastrip(&nlt->strips, strip);
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_delete (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Strips";
+ ot->idname= "NLAEDIT_OT_delete";
+ ot->description= "Delete selected strips.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_delete_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Split Strips Operator ***************************** */
+/* Splits the selected NLA-Strips into two strips at the midpoint of the strip */
+// TODO's?
+// - multiple splits
+// - variable-length splits?
+
+static int nlaedit_split_exec (bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of editable tracks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, delete all selected strips */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip, *nstrip, *next;
+
+ for (strip= nlt->strips.first; strip; strip= next) {
+ next= strip->next;
+
+ /* if selected, split the strip at its midpoint */
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ float midframe, midaframe, len;
+
+ /* calculate the frames to do the splitting at */
+ /* strip extents */
+ len= strip->end - strip->start;
+ if (IS_EQ(len, 0.0f))
+ continue;
+ else
+ midframe= strip->start + (len / 2.0f);
+
+ /* action range */
+ len= strip->actend - strip->actstart;
+ if (IS_EQ(len, 0.0f))
+ midaframe= strip->actend;
+ else
+ midaframe= strip->actstart + (len / 2.0f);
+
+ /* make a copy (assume that this is possible) and append
+ * it immediately after the current strip
+ */
+ nstrip= copy_nlastrip(strip);
+ BLI_insertlinkafter(&nlt->strips, strip, nstrip);
+
+ /* set the endpoint of the first strip and the start of the new strip
+ * to the midframe values calculated above
+ */
+ strip->end= midframe;
+ nstrip->start= midframe;
+
+ strip->actend= midaframe;
+ nstrip->actstart= midaframe;
+ }
+ }
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+ WM_event_add_notifier(C, NC_SCENE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_split (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Split Strips";
+ ot->idname= "NLAEDIT_OT_split";
+ ot->description= "Split selected strips at their midpoints.";
+
+ /* api callbacks */
+ ot->exec= nlaedit_split_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c
index 0f6b77da6f5..f8c6ba2131a 100644
--- a/source/blender/editors/space_nla/nla_header.c
+++ b/source/blender/editors/space_nla/nla_header.c
@@ -29,6 +29,10 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -37,69 +41,143 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "BKE_animsys.h"
+#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_report.h"
#include "BKE_screen.h"
-
-#include "ED_screen.h"
#include "ED_types.h"
#include "ED_util.h"
-#include "WM_api.h"
-#include "WM_types.h"
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "BIF_transform.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "nla_intern.h"
+#include "ED_markers.h"
+/* button events */
+enum {
+ B_REDR = 0,
+} eActHeader_ButEvents;
/* ************************ header area region *********************** */
-static void do_viewmenu(bContext *C, void *arg, int event)
+
+static void nla_viewmenu(bContext *C, uiLayout *layout, void *arg_unused)
{
+ bScreen *sc= CTX_wm_screen(C);
+ ScrArea *sa= CTX_wm_area(C);
+ Scene *scene= CTX_data_scene(C);
+ SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C);
+ PointerRNA spaceptr;
+
+ /* retrieve state */
+ RNA_pointer_create(&sc->id, &RNA_SpaceNLA, snla, &spaceptr);
+
+ /* create menu */
+ uiItemO(layout, NULL, ICON_MENU_PANEL, "NLAEDIT_OT_properties");
+
+ uiItemS(layout);
+ uiItemR(layout, NULL, 0, &spaceptr, "show_cframe_indicator", 0, 0, 0);
+
+ if (snla->flag & SNLA_DRAWTIME)
+ uiItemO(layout, "Show Frames", 0, "ANIM_OT_time_toggle");
+ else
+ uiItemO(layout, "Show Seconds", 0, "ANIM_OT_time_toggle");
+
+ uiItemS(layout);
+
+ if (scene->flag & SCE_NLA_EDIT_ON)
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_tweakmode_exit");
+ else
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_tweakmode_enter");
+
+ uiItemS(layout);
+
+ //uiItemO(layout, NULL, 0, "NLA_OT_view_all");
+
+ if (sa->full)
+ uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Tile Window", Ctrl UpArrow
+ else
+ uiItemO(layout, NULL, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctr DownArrow
}
-static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
+static void nla_selectmenu(bContext *C, uiLayout *layout, void *arg_unused)
{
- ScrArea *curarea= CTX_wm_area(C);
- uiBlock *block;
- short yco= 0, menuwidth=120;
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_select_all_toggle");
+ uiItemBooleanO(layout, "Invert All", 0, "NLAEDIT_OT_select_all_toggle", "invert", 1);
- block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP);
- uiBlockSetButmFunc(block, do_viewmenu, NULL);
+ uiItemS(layout);
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_select_border");
+ uiItemBooleanO(layout, "Border Axis Range", 0, "NLAEDIT_OT_select_border", "axis_range", 1);
+}
+
+static void nla_edit_transformmenu(bContext *C, uiLayout *layout, void *arg_unused)
+{
+ // XXX these operators may change for NLA...
+ uiItemEnumO(layout, "Grab/Move", 0, "TFM_OT_transform", "mode", TFM_TIME_TRANSLATE);
+ uiItemEnumO(layout, "Extend", 0, "TFM_OT_transform", "mode", TFM_TIME_EXTEND);
+ uiItemEnumO(layout, "Scale", 0, "TFM_OT_transform", "mode", TFM_TIME_SCALE);
+}
+
+static void nla_editmenu(bContext *C, uiLayout *layout, void *arg_unused)
+{
+ uiItemMenuF(layout, "Transform", 0, nla_edit_transformmenu);
- if(curarea->headertype==HEADERTOP) {
- uiBlockSetDirection(block, UI_DOWN);
- }
- else {
- uiBlockSetDirection(block, UI_TOP);
- uiBlockFlipOrder(block);
- }
+ uiItemS(layout);
- uiTextBoundsBlock(block, 50);
- uiEndBlock(C, block);
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_duplicate");
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_split");
- return block;
+ uiItemS(layout);
+
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_delete");
}
+static void nla_addmenu(bContext *C, uiLayout *layout, void *arg_unused)
+{
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_actionclip");
+ uiItemO(layout, NULL, 0, "NLAEDIT_OT_add_transition");
+
+ uiItemS(layout);
+
+ uiItemO(layout, NULL, 0, "NLA_OT_add_tracks");
+ uiItemBooleanO(layout, "Add Tracks Above Selected", 0, "NLA_OT_add_tracks", "above_selected", 1);
+}
+
+/* ------------------ */
+
static void do_nla_buttons(bContext *C, void *arg, int event)
{
- switch(event) {
+ switch (event) {
+ case B_REDR:
+ ED_area_tag_redraw(CTX_wm_area(C));
+ break;
}
}
void nla_header_buttons(const bContext *C, ARegion *ar)
{
+ SpaceNla *snla= (SpaceNla *)CTX_wm_space_data(C);
+ Scene *scene= CTX_data_scene(C);
ScrArea *sa= CTX_wm_area(C);
uiBlock *block;
int xco, yco= 3;
@@ -109,17 +187,76 @@ void nla_header_buttons(const bContext *C, ARegion *ar)
xco= ED_area_header_standardbuttons(C, block, yco);
- if((sa->flag & HEADER_NO_PULLDOWN)==0) {
+ if ((sa->flag & HEADER_NO_PULLDOWN)==0) {
int xmax;
xmax= GetButStringLength("View");
- uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C),
- "View", xco, yco-2, xmax-3, 24, "");
- xco+=XIC+xmax;
+ uiDefMenuBut(block, nla_viewmenu, NULL, "View", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Select");
+ uiDefMenuBut(block, nla_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Edit");
+ uiDefMenuBut(block, nla_editmenu, NULL, "Edit", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
+
+ xmax= GetButStringLength("Add");
+ uiDefMenuBut(block, nla_addmenu, NULL, "Add", xco, yco, xmax-3, 20, "");
+ xco+= xmax;
}
uiBlockSetEmboss(block, UI_EMBOSS);
-
+
+ /* filtering buttons */
+ if (snla->ads) {
+ uiBlockBeginAlign(block);
+ uiDefIconButBitI(block, TOG, ADS_FILTER_ONLYSEL, B_REDR, ICON_RESTRICT_SELECT_OFF, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Only display selected Objects");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NLA_NOACT, B_REDR, ICON_ACTION, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Include AnimData blocks with no NLA Data");
+ uiBlockEndAlign(block);
+ xco += 5;
+
+ uiBlockBeginAlign(block);
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSCE, B_REDR, ICON_SCENE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Scene Animation");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOWOR, B_REDR, ICON_WORLD_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display World Animation");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSHAPEKEYS, B_REDR, ICON_SHAPEKEY_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display ShapeKeys");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMAT, B_REDR, ICON_MATERIAL_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Materials");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOLAM, B_REDR, ICON_LAMP_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Lamps");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCAM, B_REDR, ICON_CAMERA_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Cameras");
+ uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCUR, B_REDR, ICON_CURVE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Curves");
+ uiBlockEndAlign(block);
+ xco += 15;
+ }
+ else {
+ // XXX this case shouldn't happen at all... for now, just pad out same amount of space
+ xco += 7*XIC + 15;
+ }
+ xco += (XIC + 8);
+
+ /* auto-snap selector */
+ if (snla->flag & SNLA_DRAWTIME) {
+ uiDefButS(block, MENU, B_REDR,
+ "Auto-Snap Keyframes %t|No Time-Snap %x0|Nearest Second %x2|Nearest Marker %x3",
+ xco,yco,90,YIC, &snla->autosnap, 0, 1, 0, 0,
+ "Auto-snapping mode for times when transforming");
+ }
+ else {
+ uiDefButS(block, MENU, B_REDR,
+ "Auto-Snap Keyframes %t|No Time-Snap %x0|Nearest Frame %x2|Nearest Marker %x3",
+ xco,yco,90,YIC, &snla->autosnap, 0, 1, 0, 0,
+ "Auto-snapping mode for times when transforming");
+ }
+ xco += 98;
+
+ /* Tweakmode... */
+ // XXX these icons need to be changed
+ if (scene->flag & SCE_NLA_EDIT_ON)
+ uiDefIconTextButO(block, BUT, "NLAEDIT_OT_tweakmode_exit", WM_OP_INVOKE_REGION_WIN, ICON_NLA, "Exit TweakMode", xco,yco,130,YIC, "Restore the true active action. (TAB)");
+ else
+ uiDefIconTextButO(block, BUT, "NLAEDIT_OT_tweakmode_enter", WM_OP_INVOKE_REGION_WIN, ICON_EDIT, "Enter TweakMode", xco,yco,130,YIC, "Temporarily set the action referenced by the active strip as the active action so that it can be tweaked. (TAB)");
+ xco+= 150;
+
/* always as last */
UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index c544bd9a408..1237542172f 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -17,11 +17,11 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung.
* All rights reserved.
*
*
- * Contributor(s): Blender Foundation
+ * Contributor(s): Blender Foundation, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -30,10 +30,93 @@
/* internal exports only */
+/* **************************************** */
+/* Macros, etc. only used by NLA */
+/* -------------- NLA Channel Defines -------------- */
+
+/* NLA channel heights */
+#define NLACHANNEL_FIRST -16
+#define NLACHANNEL_HEIGHT 24
+#define NLACHANNEL_HEIGHT_HALF 12
+#define NLACHANNEL_SKIP 2
+#define NLACHANNEL_STEP (NLACHANNEL_HEIGHT + NLACHANNEL_SKIP)
+
+/* channel widths */
+#define NLACHANNEL_NAMEWIDTH 200
+
+/* channel toggle-buttons */
+#define NLACHANNEL_BUTTON_WIDTH 16
+
+/* **************************************** */
+/* space_nla.c / nla_buttons.c */
+
+ARegion *nla_has_buttons_region(ScrArea *sa);
+
+void nla_buttons_register(ARegionType *art);
+void NLAEDIT_OT_properties(wmOperatorType *ot);
+
+/* **************************************** */
+/* nla_draw.c */
+
+void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar);
+void draw_nla_channel_list(bAnimContext *ac, SpaceNla *snla, ARegion *ar);
+
+/* **************************************** */
/* nla_header.c */
+
void nla_header_buttons(const bContext *C, ARegion *ar);
+/* **************************************** */
+/* nla_select.c */
+
+/* defines for left-right select tool */
+enum {
+ NLAEDIT_LRSEL_TEST = -1,
+ NLAEDIT_LRSEL_NONE,
+ NLAEDIT_LRSEL_LEFT,
+ NLAEDIT_LRSEL_RIGHT,
+} eNlaEdit_LeftRightSelect_Mode;
+
+/* --- */
+
+void NLAEDIT_OT_select_all_toggle(wmOperatorType *ot);
+void NLAEDIT_OT_select_border(wmOperatorType *ot);
+void NLAEDIT_OT_click_select(wmOperatorType *ot);
+
+/* **************************************** */
+/* nla_edit.c */
+
+void NLAEDIT_OT_tweakmode_enter(wmOperatorType *ot);
+void NLAEDIT_OT_tweakmode_exit(wmOperatorType *ot);
+
+/* --- */
+
+void NLAEDIT_OT_add_actionclip(wmOperatorType *ot);
+void NLAEDIT_OT_add_transition(wmOperatorType *ot);
+
+void NLAEDIT_OT_duplicate(wmOperatorType *ot);
+void NLAEDIT_OT_delete(wmOperatorType *ot);
+void NLAEDIT_OT_split(wmOperatorType *ot);
+
+
+/* **************************************** */
+/* nla_channels.c */
+
+void NLA_OT_channels_click(wmOperatorType *ot);
+
+void NLA_OT_add_tracks(wmOperatorType *ot);
+
+/* **************************************** */
+/* nla_ops.c */
+
+int nlaop_poll_tweakmode_off(bContext *C);
+int nlaop_poll_tweakmode_on (bContext *C);
+
+/* --- */
+
+void nla_operatortypes(void);
+void nla_keymap(wmWindowManager *wm);
#endif /* ED_NLA_INTERN_H */
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
new file mode 100644
index 00000000000..52b529661cb
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -0,0 +1,257 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung (major recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_animsys.h"
+#include "BKE_nla.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+
+#include "ED_anim_api.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_transform.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "nla_intern.h" // own include
+
+/* ************************** poll callbacks for operators **********************************/
+
+/* tweakmode is NOT enabled */
+int nlaop_poll_tweakmode_off (bContext *C)
+{
+ Scene *scene;
+
+ /* for now, we check 2 things:
+ * 1) active editor must be NLA
+ * 2) tweakmode is currently set as a 'per-scene' flag
+ * so that it will affect entire NLA data-sets,
+ * but not all AnimData blocks will be in tweakmode for
+ * various reasons
+ */
+ if (ED_operator_nla_active(C) == 0)
+ return 0;
+
+ scene= CTX_data_scene(C);
+ if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
+ return 0;
+
+ return 1;
+}
+
+/* tweakmode IS enabled */
+int nlaop_poll_tweakmode_on (bContext *C)
+{
+ Scene *scene;
+
+ /* for now, we check 2 things:
+ * 1) active editor must be NLA
+ * 2) tweakmode is currently set as a 'per-scene' flag
+ * so that it will affect entire NLA data-sets,
+ * but not all AnimData blocks will be in tweakmode for
+ * various reasons
+ */
+ if (ED_operator_nla_active(C) == 0)
+ return 0;
+
+ scene= CTX_data_scene(C);
+ if ((scene == NULL) || !(scene->flag & SCE_NLA_EDIT_ON))
+ return 0;
+
+ return 1;
+}
+
+/* ************************** registration - operator types **********************************/
+
+void nla_operatortypes(void)
+{
+ /* view */
+ WM_operatortype_append(NLAEDIT_OT_properties);
+
+ /* channels */
+ WM_operatortype_append(NLA_OT_channels_click);
+
+ WM_operatortype_append(NLA_OT_add_tracks);
+
+ /* select */
+ WM_operatortype_append(NLAEDIT_OT_click_select);
+ WM_operatortype_append(NLAEDIT_OT_select_border);
+ WM_operatortype_append(NLAEDIT_OT_select_all_toggle);
+
+ /* edit */
+ WM_operatortype_append(NLAEDIT_OT_tweakmode_enter);
+ WM_operatortype_append(NLAEDIT_OT_tweakmode_exit);
+
+ WM_operatortype_append(NLAEDIT_OT_add_actionclip);
+ WM_operatortype_append(NLAEDIT_OT_add_transition);
+
+ WM_operatortype_append(NLAEDIT_OT_duplicate);
+ WM_operatortype_append(NLAEDIT_OT_delete);
+ WM_operatortype_append(NLAEDIT_OT_split);
+}
+
+/* ************************** registration - keymaps **********************************/
+
+static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap)
+{
+ /* NLA-specific (different to standard channels keymap) -------------------------- */
+ /* selection */
+ /* click-select */
+ // XXX for now, only leftmouse....
+ WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+
+ /* channel operations */
+ /* add tracks */
+ WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "NLA_OT_add_tracks", AKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "above_selected", 1);
+
+ /* General Animation Channels keymap (see anim_channels.c) ----------------------- */
+ /* selection */
+ /* borderselect */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
+
+ /* deselect all */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
+
+ /* settings */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_disable", WKEY, KM_PRESS, KM_ALT, 0);
+
+ /* settings - specialised hotkeys */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0);
+
+ /* expand/collapse */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, 0, 0);
+
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "all", 1);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, KM_CTRL, 0)->ptr, "all", 1);
+}
+
+static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap)
+{
+ wmKeymapItem *kmi;
+
+ /* selection */
+ /* click select */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ kmi= WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", 1);
+ kmi= WM_keymap_add_item(keymap, "NLAEDIT_OT_click_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "left_right", NLAEDIT_LRSEL_TEST);
+
+ /* deselect all */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
+
+ /* borderselect */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_select_border", BKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "NLAEDIT_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0)->ptr, "axis_range", 1);
+
+
+ /* editing */
+ /* tweakmode
+ * - enter and exit are separate operators with the same hotkey...
+ * This works as they use different poll()'s
+ */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0);
+
+ /* add strips */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_add_actionclip", AKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_add_transition", TKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* duplicate */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+
+ /* delete */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_delete", DELKEY, KM_PRESS, 0, 0);
+
+ /* split */
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_split", YKEY, KM_PRESS, 0, 0);
+
+ /* transform system */
+ transform_keymap_for_space(wm, keymap, SPACE_NLA);
+}
+
+/* --------------- */
+
+void nla_keymap(wmWindowManager *wm)
+{
+ ListBase *keymap;
+
+ /* keymap for all regions */
+ keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
+ WM_keymap_add_item(keymap, "NLAEDIT_OT_properties", NKEY, KM_PRESS, 0, 0);
+
+ /* channels */
+ /* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module.
+ * Most of the relevant operations, keymaps, drawing, etc. can therefore all be found in that module instead, as there
+ * are many similarities with the other Animation Editors.
+ *
+ * However, those operations which involve clicking on channels and/or the placement of them in the view are implemented here instead
+ */
+ keymap= WM_keymap_listbase(wm, "NLA Channels", SPACE_NLA, 0);
+ nla_keymap_channels(wm, keymap);
+
+ /* data */
+ keymap= WM_keymap_listbase(wm, "NLA Data", SPACE_NLA, 0);
+ nla_keymap_main(wm, keymap);
+}
+
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
new file mode 100644
index 00000000000..b850ec76f82
--- /dev/null
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -0,0 +1,600 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joshua Leung (major recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_animsys.h"
+#include "BKE_nla.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframes_edit.h"
+#include "ED_markers.h"
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "nla_intern.h" // own include
+
+/* ******************** Utilities ***************************************** */
+
+/* Convert SELECT_* flags to ACHANNEL_SETFLAG_* flags */
+static short selmodes_to_flagmodes (short sel)
+{
+ /* convert selection modes to selection modes */
+ switch (sel) {
+ case SELECT_SUBTRACT:
+ return ACHANNEL_SETFLAG_CLEAR;
+ break;
+
+ case SELECT_INVERT:
+ return ACHANNEL_SETFLAG_TOGGLE;
+ break;
+
+ case SELECT_ADD:
+ default:
+ return ACHANNEL_SETFLAG_ADD;
+ break;
+ }
+}
+
+
+/* ******************** Deselect All Operator ***************************** */
+/* This operator works in one of three ways:
+ * 1) (de)select all (AKEY) - test if select all or deselect all
+ * 2) invert all (CTRL-IKEY) - invert selection of all keyframes
+ * 3) (de)select all - no testing is done; only for use internal tools as normal function...
+ */
+
+enum {
+ DESELECT_STRIPS_NOTEST = 0,
+ DESELECT_STRIPS_TEST,
+ DESELECT_STRIPS_CLEARACTIVE,
+} eDeselectNlaStrips;
+
+/* Deselects strips in the NLA Editor
+ * - This is called by the deselect all operator, as well as other ones!
+ *
+ * - test: check if select or deselect all (1) or clear all active (2)
+ * - sel: how to select keyframes
+ * 0 = deselect
+ * 1 = select
+ * 2 = invert
+ */
+static void deselect_nla_strips (bAnimContext *ac, short test, short sel)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ short smode;
+
+ /* determine type-based settings */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS);
+
+ /* filter data */
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* See if we should be selecting or deselecting */
+ if (test == DESELECT_STRIPS_TEST) {
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* if any strip is selected, break out, since we should now be deselecting */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ sel= SELECT_SUBTRACT;
+ break;
+ }
+ }
+
+ if (sel == SELECT_SUBTRACT)
+ break;
+ }
+ }
+
+ /* convert selection modes to selection modes */
+ smode= selmodes_to_flagmodes(sel);
+
+ /* Now set the flags */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* apply same selection to all strips */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ /* set selection */
+ if (test != DESELECT_STRIPS_CLEARACTIVE)
+ ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT);
+
+ /* clear active flag */
+ // TODO: for clear active, do we want to limit this to only doing this on a certain set of tracks though?
+ strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
+ }
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int nlaedit_deselectall_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* 'standard' behaviour - check if selected, then apply relevant selection */
+ if (RNA_boolean_get(op->ptr, "invert"))
+ deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT);
+ else
+ deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD);
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_select_all_toggle (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select All";
+ ot->idname= "NLAEDIT_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= nlaedit_deselectall_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
+}
+
+/* ******************** Border Select Operator **************************** */
+/* This operator currently works in one of three ways:
+ * -> BKEY - 1) all strips within region are selected (ACTKEYS_BORDERSEL_ALLSTRIPS)
+ * -> ALT-BKEY - depending on which axis of the region was larger...
+ * -> 2) x-axis, so select all frames within frame range (ACTKEYS_BORDERSEL_FRAMERANGE)
+ * -> 3) y-axis, so select all frames within channels that region included (ACTKEYS_BORDERSEL_CHANNELS)
+ */
+
+/* defines for borderselect mode */
+enum {
+ NLA_BORDERSEL_ALLSTRIPS = 0,
+ NLA_BORDERSEL_FRAMERANGE,
+ NLA_BORDERSEL_CHANNELS,
+} eActKeys_BorderSelect_Mode;
+
+
+static void borderselect_nla_strips (bAnimContext *ac, rcti rect, short mode, short selectmode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ View2D *v2d= &ac->ar->v2d;
+ rctf rectf;
+ float ymin=(float)(-NLACHANNEL_HEIGHT), ymax=0;
+
+ /* convert border-region to view coordinates */
+ UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin+2, &rectf.xmin, &rectf.ymin);
+ UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax-2, &rectf.xmax, &rectf.ymax);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* convert selection modes to selection modes */
+ selectmode= selmodes_to_flagmodes(selectmode);
+
+ /* loop over data, doing border select */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ ymin= ymax - NLACHANNEL_STEP;
+
+ /* perform vertical suitability check (if applicable) */
+ if ( (mode == NLA_BORDERSEL_FRAMERANGE) ||
+ !((ymax < rectf.ymin) || (ymin > rectf.ymax)) )
+ {
+ /* loop over data selecting (only if NLA-Track) */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* only select strips if they fall within the required ranges (if applicable) */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ if ( (mode == NLA_BORDERSEL_CHANNELS) ||
+ BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax) )
+ {
+ /* set selection */
+ ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT);
+
+ /* clear active flag */
+ strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
+ }
+ }
+ }
+ }
+
+ /* set minimum extent to be the maximum of the next channel */
+ ymax= ymin;
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ rcti rect;
+ short mode=0, selectmode=0;
+ int event;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get settings from operator */
+ rect.xmin= RNA_int_get(op->ptr, "xmin");
+ rect.ymin= RNA_int_get(op->ptr, "ymin");
+ rect.xmax= RNA_int_get(op->ptr, "xmax");
+ rect.ymax= RNA_int_get(op->ptr, "ymax");
+
+ event= RNA_int_get(op->ptr, "event_type");
+ if (event == LEFTMOUSE) // FIXME... hardcoded
+ selectmode = SELECT_ADD;
+ else
+ selectmode = SELECT_SUBTRACT;
+
+ /* selection 'mode' depends on whether borderselect region only matters on one axis */
+ if (RNA_boolean_get(op->ptr, "axis_range")) {
+ /* mode depends on which axis of the range is larger to determine which axis to use
+ * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
+ * - the frame-range select option is favoured over the channel one (x over y), as frame-range one is often
+ * used for tweaking timing when "blocking", while channels is not that useful...
+ */
+ if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin))
+ mode= NLA_BORDERSEL_FRAMERANGE;
+ else
+ mode= NLA_BORDERSEL_CHANNELS;
+ }
+ else
+ mode= NLA_BORDERSEL_ALLSTRIPS;
+
+ /* apply borderselect action */
+ borderselect_nla_strips(&ac, rect, mode, selectmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void NLAEDIT_OT_select_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Border Select";
+ ot->idname= "NLAEDIT_OT_select_border";
+
+ /* api callbacks */
+ ot->invoke= WM_border_select_invoke;
+ ot->exec= nlaedit_borderselect_exec;
+ ot->modal= WM_border_select_modal;
+
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* rna */
+ RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+
+ RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
+}
+
+/* ******************** Mouse-Click Select Operator *********************** */
+/* This operator works in one of 2 ways:
+ * 1) Select the strip directly under the mouse
+ * 2) Select all the strips to one side of the mouse
+ */
+
+/* defines for left-right select tool */
+static EnumPropertyItem prop_nlaedit_leftright_select_types[] = {
+ {NLAEDIT_LRSEL_TEST, "CHECK", "Check if Select Left or Right", ""},
+ {NLAEDIT_LRSEL_NONE, "OFF", "Don't select", ""},
+ {NLAEDIT_LRSEL_LEFT, "LEFT", "Before current frame", ""},
+ {NLAEDIT_LRSEL_RIGHT, "RIGHT", "After current frame", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* sensitivity factor for frame-selections */
+#define FRAME_CLICK_THRESH 0.1f
+
+
+/* ------------------- */
+
+/* option 1) select strip directly under mouse */
+static void mouse_nla_strips (bAnimContext *ac, int mval[2], short select_mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale = NULL;
+ int filter;
+
+ View2D *v2d= &ac->ar->v2d;
+ NlaStrip *strip = NULL;
+ int channel_index;
+ float xmin, xmax, dummy;
+ float x, y;
+
+
+ /* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+ UI_view2d_listview_view_to_cell(v2d, 0, NLACHANNEL_STEP, 0, (float)NLACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
+
+ /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
+ * (that is the size of keyframe icons, so user should be expecting similar tolerances)
+ */
+ UI_view2d_region_to_view(v2d, mval[0]-7, mval[1], &xmin, &dummy);
+ UI_view2d_region_to_view(v2d, mval[0]+7, mval[1], &xmax, &dummy);
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* try to get channel */
+ ale= BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ printf("Error: animation channel (index = %d) not found in mouse_nla_strips() \n", channel_index);
+ BLI_freelistN(&anim_data);
+ return;
+ }
+ else {
+ /* found some channel - we only really should do somethign when its an Nla-Track */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+
+ /* loop over NLA-strips in this track, trying to find one which occurs in the necessary bounds */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ if (BKE_nlastrip_within_bounds(strip, xmin, xmax))
+ break;
+ }
+ }
+
+ /* remove active channel from list of channels for separate treatment (since it's needed later on) */
+ BLI_remlink(&anim_data, ale);
+
+ /* free list of channels, since it's not used anymore */
+ BLI_freelistN(&anim_data);
+ }
+
+ /* for replacing selection, firstly need to clear existing selection */
+ if (select_mode == SELECT_REPLACE) {
+ /* reset selection mode for next steps */
+ select_mode = SELECT_ADD;
+
+ /* deselect all strips */
+ deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
+
+ /* deselect all other channels first */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+ /* Highlight NLA-Track */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+
+ nlt->flag |= NLATRACK_SELECTED;
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
+ }
+ }
+
+ /* only select strip if we clicked on a valid channel and hit something */
+ if (ale) {
+ /* select the strip accordingly (if a matching one was found) */
+ if (strip) {
+ select_mode= selmodes_to_flagmodes(select_mode);
+ ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
+
+ /* if we selected it, we can make it active too
+ * - we always need to clear the active strip flag though...
+ */
+ deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0);
+ if (strip->flag & NLASTRIP_FLAG_SELECT)
+ strip->flag |= NLASTRIP_FLAG_ACTIVE;
+ }
+
+ /* free this channel */
+ MEM_freeN(ale);
+ }
+}
+
+/* Option 2) Selects all the strips on either side of the current frame (depends on which side the mouse is on) */
+static void nlaedit_mselect_leftright (bAnimContext *ac, short leftright, short select_mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ Scene *scene= ac->scene;
+ float xmin, xmax;
+
+ /* if select mode is replace, deselect all keyframes (and channels) first */
+ if (select_mode==SELECT_REPLACE) {
+ select_mode= SELECT_ADD;
+
+ /* deselect all other channels and keyframes */
+ ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
+ }
+
+ /* get range, and get the right flag-setting mode */
+ if (leftright == NLAEDIT_LRSEL_LEFT) {
+ xmin = -MAXFRAMEF;
+ xmax = (float)(CFRA + FRAME_CLICK_THRESH);
+ }
+ else {
+ xmin = (float)(CFRA - FRAME_CLICK_THRESH);
+ xmax = MAXFRAMEF;
+ }
+
+ select_mode= selmodes_to_flagmodes(select_mode);
+
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* select strips on the side where most data occurs */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* check each strip to see if it is appropriate */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) {
+ ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
+ }
+ }
+ }
+
+ /* Cleanup */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+/* handle clicking */
+static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ bAnimContext ac;
+ Scene *scene;
+ ARegion *ar;
+ View2D *v2d;
+ short selectmode;
+ int mval[2];
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get useful pointers from animation context data */
+ scene= ac.scene;
+ ar= ac.ar;
+ v2d= &ar->v2d;
+
+ /* get mouse coordinates (in region coordinates) */
+ mval[0]= (event->x - ar->winrct.xmin);
+ mval[1]= (event->y - ar->winrct.ymin);
+
+ /* select mode is either replace (deselect all, then add) or add/extend */
+ if (RNA_boolean_get(op->ptr, "extend"))
+ selectmode= SELECT_INVERT;
+ else
+ selectmode= SELECT_REPLACE;
+
+ /* figure out action to take */
+ if (RNA_enum_get(op->ptr, "left_right")) {
+ /* select all keys on same side of current frame as mouse */
+ float x;
+
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
+ if (x < CFRA)
+ RNA_int_set(op->ptr, "left_right", NLAEDIT_LRSEL_LEFT);
+ else
+ RNA_int_set(op->ptr, "left_right", NLAEDIT_LRSEL_RIGHT);
+
+ nlaedit_mselect_leftright(&ac, RNA_enum_get(op->ptr, "left_right"), selectmode);
+ }
+ else {
+ /* select strips based upon mouse position */
+ mouse_nla_strips(&ac, mval, selectmode);
+ }
+
+ /* set notifier that things have changed */
+ ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
+
+ /* for tweak grab to work */
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+}
+
+void NLAEDIT_OT_click_select (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mouse Select";
+ ot->idname= "NLAEDIT_OT_click_select";
+
+ /* api callbacks - absolutely no exec() this yet... */
+ ot->invoke= nlaedit_clickselect_invoke;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ // XXX should we make this into separate operators?
+ RNA_def_enum(ot->srna, "left_right", prop_nlaedit_leftright_select_types, 0, "Left Right", ""); // CTRLKEY
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
+}
+
+/* *********************************************** */
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 6e1a97dea34..a7e9844726d 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_anim_types.h"
#include "DNA_nla_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
@@ -41,10 +42,16 @@
#include "BLI_arithb.h"
#include "BLI_rand.h"
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_nla.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_screen.h"
+#include "BKE_utildefines.h"
+#include "ED_anim_api.h"
+#include "ED_markers.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -57,20 +64,58 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-#include "ED_markers.h"
-
#include "nla_intern.h" // own include
+/* ******************** manage regions ********************* */
+
+ARegion *nla_has_buttons_region(ScrArea *sa)
+{
+ ARegion *ar, *arnew;
+
+ for (ar= sa->regionbase.first; ar; ar= ar->next) {
+ if (ar->regiontype==RGN_TYPE_UI)
+ return ar;
+ }
+
+ /* add subdiv level; after main */
+ for (ar= sa->regionbase.first; ar; ar= ar->next) {
+ if (ar->regiontype==RGN_TYPE_WINDOW)
+ break;
+ }
+
+ /* is error! */
+ if (ar==NULL) return NULL;
+
+ arnew= MEM_callocN(sizeof(ARegion), "buttons for nla");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype= RGN_TYPE_UI;
+ arnew->alignment= RGN_ALIGN_RIGHT;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+
+ return arnew;
+}
+
+
+
/* ******************** default callbacks for nla space ***************** */
static SpaceLink *nla_new(const bContext *C)
{
+ Scene *scene= CTX_data_scene(C);
ARegion *ar;
SpaceNla *snla;
snla= MEM_callocN(sizeof(SpaceNla), "initnla");
snla->spacetype= SPACE_NLA;
+ /* allocate DopeSheet data for NLA Editor */
+ snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
+
+ /* set auto-snapping settings */
+ snla->autosnap = SACTSNAP_FRAME;
+
/* header */
ar= MEM_callocN(sizeof(ARegion), "header for nla");
@@ -78,13 +123,23 @@ static SpaceLink *nla_new(const bContext *C)
ar->regiontype= RGN_TYPE_HEADER;
ar->alignment= RGN_ALIGN_BOTTOM;
- /* channel list region XXX */
- ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
+ /* channel list region */
+ ar= MEM_callocN(sizeof(ARegion), "channel list for nla");
BLI_addtail(&snla->regionbase, ar);
ar->regiontype= RGN_TYPE_CHANNELS;
ar->alignment= RGN_ALIGN_LEFT;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
+ /* only need to set these settings since this will use the 'stack' configuration */
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+ ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
+
+ /* ui buttons */
+ ar= MEM_callocN(sizeof(ARegion), "buttons area for nla");
+
+ BLI_addtail(&snla->regionbase, ar);
+ ar->regiontype= RGN_TYPE_UI;
+ ar->alignment= RGN_ALIGN_RIGHT;
+ ar->flag = RGN_FLAG_HIDDEN;
/* main area */
ar= MEM_callocN(sizeof(ARegion), "main area for nla");
@@ -92,29 +147,26 @@ static SpaceLink *nla_new(const bContext *C)
BLI_addtail(&snla->regionbase, ar);
ar->regiontype= RGN_TYPE_WINDOW;
- ar->v2d.tot.xmin= 1.0f;
- ar->v2d.tot.ymin= 0.0f;
- ar->v2d.tot.xmax= 1000.0f;
- ar->v2d.tot.ymax= 1000.0f;
+ ar->v2d.tot.xmin= (float)(SFRA-10);
+ ar->v2d.tot.ymin= -500.0f;
+ ar->v2d.tot.xmax= (float)(EFRA+10);
+ ar->v2d.tot.ymax= 0.0f;
- ar->v2d.cur.xmin= -5.0f;
- ar->v2d.cur.ymin= 0.0f;
- ar->v2d.cur.xmax= 65.0f;
- ar->v2d.cur.ymax= 1000.0f;
+ ar->v2d.cur = ar->v2d.tot;
ar->v2d.min[0]= 0.0f;
- ar->v2d.min[1]= 0.0f;
+ ar->v2d.min[1]= 0.0f;
ar->v2d.max[0]= MAXFRAMEF;
- ar->v2d.max[1]= 1000.0f;
-
- ar->v2d.minzoom= 0.1f;
- ar->v2d.maxzoom= 50.0f;
-
- ar->v2d.scroll |= (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.max[1]= 10000.0f;
+
+ ar->v2d.minzoom= 0.01f;
+ ar->v2d.maxzoom= 50;
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom= V2D_LOCKZOOM_Y;
-
+ ar->v2d.align= V2D_ALIGN_NO_POS_Y;
+ ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
return (SpaceLink *)snla;
}
@@ -122,15 +174,25 @@ static SpaceLink *nla_new(const bContext *C)
/* not spacelink itself */
static void nla_free(SpaceLink *sl)
{
-// SpaceNla *snla= (SpaceNla*) sl;
+ SpaceNla *snla= (SpaceNla*) sl;
+ if (snla->ads) {
+ BLI_freelistN(&snla->ads->chanbase);
+ MEM_freeN(snla->ads);
+ }
}
/* spacetype; init callback */
static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
{
+ SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
+
+ /* init dopesheet data if non-existant (i.e. for old files) */
+ if (snla->ads == NULL)
+ snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
+ ED_area_tag_refresh(sa);
}
static SpaceLink *nla_duplicate(SpaceLink *sl)
@@ -138,15 +200,33 @@ static SpaceLink *nla_duplicate(SpaceLink *sl)
SpaceNla *snlan= MEM_dupallocN(sl);
/* clear or remove stuff from old */
+ snlan->ads= MEM_dupallocN(snlan->ads);
return (SpaceLink *)snlan;
}
+/* add handlers, stuff you only do once or on area/region changes */
+static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ /* own keymap */
+ // TODO: cannot use generic copy, need special NLA version
+ keymap= WM_keymap_listbase(wm, "NLA Channels", SPACE_NLA, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+/* draw entirely, view changes should be handled here */
static void nla_channel_area_draw(const bContext *C, ARegion *ar)
{
- /* draw entirely, view changes should be handled here */
- // SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C);
- // View2D *v2d= &ar->v2d;
+ SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C);
+ bAnimContext ac;
+ View2D *v2d= &ar->v2d;
+ View2DScrollers *scrollers;
float col[3];
/* clear and setup matrix */
@@ -154,15 +234,20 @@ static void nla_channel_area_draw(const bContext *C, ARegion *ar)
glClearColor(col[0], col[1], col[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT);
- // UI_view2d_view_ortho(C, v2d);
-
- /* data... */
+ UI_view2d_view_ortho(C, v2d);
+ /* data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ draw_nla_channel_list(&ac, snla, ar);
+ }
/* reset view matrix */
- //UI_view2d_view_restore(C);
+ UI_view2d_view_restore(C);
- /* scrollers? */
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
@@ -174,16 +259,22 @@ static void nla_main_area_init(wmWindowManager *wm, ARegion *ar)
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
/* own keymap */
- keymap= WM_keymap_listbase(wm, "NLA", SPACE_NLA, 0); /* XXX weak? */
+ keymap= WM_keymap_listbase(wm, "NLA Data", SPACE_NLA, 0); /* XXX weak? */
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+ keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void nla_main_area_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
- // SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C);
+ SpaceNla *snla= (SpaceNla*)CTX_wm_space_data(C);
+ bAnimContext ac;
View2D *v2d= &ar->v2d;
+ View2DGrid *grid;
+ View2DScrollers *scrollers;
float col[3];
+ short unit=0, flag=0;
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
@@ -191,25 +282,46 @@ static void nla_main_area_draw(const bContext *C, ARegion *ar)
glClear(GL_COLOR_BUFFER_BIT);
UI_view2d_view_ortho(C, v2d);
+
+ /* time grid */
+ unit= (snla->flag & SNLA_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMES;
+ grid= UI_view2d_grid_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
+ UI_view2d_grid_draw(C, v2d, grid, V2D_GRIDLINES_ALL);
+ UI_view2d_grid_free(grid);
+
+ /* data */
+ if (ANIM_animdata_get_context(C, &ac)) {
+ /* strips and backdrops */
+ draw_nla_main_data(&ac, snla, ar);
- /* data... */
+ /* text draw cached, in pixelspace now */
+ UI_view2d_text_cache_draw(ar);
+ }
+ UI_view2d_view_ortho(C, v2d);
+
+ /* current frame */
+ if (snla->flag & SNLA_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
+ if ((snla->flag & SNLA_NODRAWCFRANUM)==0) flag |= DRAWCFRA_SHOW_NUMBOX;
+ ANIM_draw_cfra(C, v2d, flag);
+
+ /* markers */
+ UI_view2d_view_orthoSpecial(C, v2d, 1);
+ draw_markers_time(C, 0);
+
+ /* preview range */
+ UI_view2d_view_ortho(C, v2d);
+ ANIM_draw_previewrange(C, v2d);
/* reset view matrix */
UI_view2d_view_restore(C);
- /* scrollers? */
+ /* scrollers */
+ scrollers= UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
}
-void nla_operatortypes(void)
-{
-
-}
-
-void nla_keymap(struct wmWindowManager *wm)
-{
-
-}
/* add handlers, stuff you only do once or on area/region changes */
static void nla_header_area_init(wmWindowManager *wm, ARegion *ar)
@@ -239,9 +351,131 @@ static void nla_header_area_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
}
+/* add handlers, stuff you only do once or on area/region changes */
+static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ ED_region_panels_init(wm, ar);
+
+ keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void nla_buttons_area_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_panels(C, ar, 1, NULL);
+}
+
+static void nla_region_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ default:
+ if(wmn->data==ND_KEYS)
+ ED_region_tag_redraw(ar);
+
+ }
+}
+
+
static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn)
{
/* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ case ND_MARKERS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ case ND_TRANSFORM:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ default:
+ if(wmn->data==ND_KEYS)
+ ED_region_tag_redraw(ar);
+ }
+}
+
+static void nla_channel_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+ /* context changes */
+ switch(wmn->category) {
+ case NC_SCENE:
+ switch(wmn->data) {
+ case ND_OB_ACTIVE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_OBJECT:
+ switch(wmn->data) {
+ case ND_BONE_ACTIVE:
+ case ND_BONE_SELECT:
+ case ND_KEYS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ default:
+ if(wmn->data==ND_KEYS)
+ ED_region_tag_redraw(ar);
+ }
+}
+
+/* editor level listener */
+static void nla_listener(ScrArea *sa, wmNotifier *wmn)
+{
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ /*switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ case ND_OB_SELECT:
+ ED_area_tag_refresh(sa);
+ break;
+ }*/
+ ED_area_tag_refresh(sa);
+ break;
+ case NC_OBJECT:
+ /*switch (wmn->data) {
+ case ND_BONE_SELECT:
+ case ND_BONE_ACTIVE:
+ ED_area_tag_refresh(sa);
+ break;
+ }*/
+ ED_area_tag_refresh(sa);
+ break;
+ }
}
/* only called once, from space/spacetypes.c */
@@ -257,6 +491,7 @@ void ED_spacetype_nla(void)
st->init= nla_init;
st->duplicate= nla_duplicate;
st->operatortypes= nla_operatortypes;
+ st->listener= nla_listener;
st->keymap= nla_keymap;
/* regions: main window */
@@ -265,7 +500,7 @@ void ED_spacetype_nla(void)
art->init= nla_main_area_init;
art->draw= nla_main_area_draw;
art->listener= nla_main_area_listener;
- art->keymapflag= ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES;
+ art->keymapflag= ED_KEYMAP_VIEW2D/*|ED_KEYMAP_MARKERS*/|ED_KEYMAP_ANIMATION|ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -286,10 +521,24 @@ void ED_spacetype_nla(void)
art->minsizex= 200;
art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
- //art->init= nla_channel_area_init;
+ art->init= nla_channel_area_init;
art->draw= nla_channel_area_draw;
+ art->listener= nla_channel_area_listener;
+
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: UI buttons */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype nla region");
+ art->regionid = RGN_TYPE_UI;
+ art->minsizex= 200;
+ art->keymapflag= ED_KEYMAP_UI;
+ art->listener= nla_region_listener;
+ art->init= nla_buttons_area_init;
+ art->draw= nla_buttons_area_draw;
BLI_addhead(&st->regiontypes, art);
+
+ nla_buttons_register(art);
BKE_spacetype_register(st);
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c
index 16748af39d5..eba0aa84e85 100644
--- a/source/blender/editors/space_outliner/outliner.c
+++ b/source/blender/editors/space_outliner/outliner.c
@@ -949,7 +949,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
/* NLA Data */
if (adt->nla_tracks.first) {
-#if 0
TreeElement *tenla= outliner_add_element(soops, &te->subtree, adt, te, TSE_NLA, 0);
NlaTrack *nlt;
int a= 0;
@@ -957,17 +956,18 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
tenla->name= "NLA Tracks";
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
- TreeElement *tenlt= outliner_add_element(soops, &te->subtree, nlt, te, TSE_NLA_TRACK, a);
- bActionStrip *strip;
+ TreeElement *tenlt= outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a);
+ NlaStrip *strip;
TreeElement *ten;
int b= 0;
- for (strip=nlt->strips.first; strip; strip=strip->next, a++) {
- ten= outliner_add_element(soops, &tenla->subtree, strip->act, tenla, TSE_NLA_ACTION, a);
+ tenlt->name= nlt->name;
+
+ for (strip=nlt->strips.first; strip; strip=strip->next, b++) {
+ ten= outliner_add_element(soops, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b);
if(ten) ten->directdata= strip;
}
}
-#endif
}
}
else if(type==TSE_SEQUENCE) {
@@ -3521,6 +3521,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx
case TSE_NLA:
UI_icon_draw(x, y, ICON_NLA); break;
+ case TSE_NLA_TRACK:
+ UI_icon_draw(x, y, ICON_NLA); break; // XXX
case TSE_NLA_ACTION:
UI_icon_draw(x, y, ICON_ACTION); break;
case TSE_DEFGROUP_BASE:
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 48c904121a5..204298f2b70 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -94,6 +94,7 @@ typedef struct TreeElement {
#define TSE_RNA_STRUCT 30
#define TSE_RNA_PROPERTY 31
#define TSE_RNA_ARRAY_ELEM 32
+#define TSE_NLA_TRACK 33
/* outliner search flags */
#define OL_FIND 0
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 6e33b1dcaab..eaff77aabe9 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -393,7 +393,6 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
case ND_GEOM_DATA:
case ND_DRAW:
case ND_MODIFIER:
- case ND_CONSTRAINT:
case ND_KEYS:
case ND_PARTICLE:
ED_region_tag_redraw(ar);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 674de81a9f5..fa93d2a143d 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -319,6 +319,9 @@ static void viewRedrawForce(bContext *C, TransInfo *t)
else
ED_area_tag_redraw(t->sa);
}
+ else if (t->spacetype == SPACE_NLA) {
+ ED_area_tag_redraw(t->sa); // XXX this should use a notifier instead!
+ }
else if(t->spacetype == SPACE_NODE)
{
//ED_area_tag_redraw(t->sa);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index ee767fada58..c0a57a85033 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -161,6 +161,13 @@ typedef struct TransDataSeq {
} TransDataSeq;
+/* for NLA transform (stored in td->extra pointer) */
+typedef struct TransDataNla {
+ struct NlaStrip *strip; /* NLA-strip that handle belongs to */
+ float val; /* value for the handle that the transform tools write to */
+ int handle; /* handle-index, 0 for start, 1 for end */
+} TransDataNla;
+
typedef struct TransData {
float dist; /* Distance needed to affect element (for Proportionnal Editing) */
float rdist; /* Distance to the nearest element (for Proportionnal Editing) */
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 6c7aa1ee49d..fb7d9c57eaf 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2559,7 +2559,137 @@ int clipUVTransform(TransInfo *t, float *vec, int resize)
return (clipx || clipy);
}
-/* ********************* ACTION/NLA EDITOR ****************** */
+/* ********************* ANIMATION EDITORS (GENERAL) ************************* */
+
+/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
+static short FrameOnMouseSide(char side, float frame, float cframe)
+{
+ /* both sides, so it doesn't matter */
+ if (side == 'B') return 1;
+
+ /* only on the named side */
+ if (side == 'R')
+ return (frame >= cframe) ? 1 : 0;
+ else
+ return (frame <= cframe) ? 1 : 0;
+}
+
+/* ********************* NLA EDITOR ************************* */
+
+static void createTransNlaData(bContext *C, TransInfo *t)
+{
+ Scene *scene= CTX_data_scene(C);
+ TransData *td = NULL;
+ TransDataNla *tdn = NULL;
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ int count=0;
+ char side;
+
+ /* determine what type of data we are operating on */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* which side of the current frame should be allowed */
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ float xmouse, ymouse;
+
+ UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
+ side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ side = 'B';
+ }
+
+ /* loop 1: count how many strips are selected (consider each strip as 2 points) */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* only consider selected strips */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ // TODO: we can make strips have handles later on...
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++;
+ if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++;
+ }
+ }
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* cleanup temp list */
+ BLI_freelistN(&anim_data);
+ return;
+ }
+
+ /* allocate memory for data */
+ t->total= count;
+
+ t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)");
+ td= t->data;
+ t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)");
+ tdn= t->customData;
+
+ /* loop 2: build transdata array */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ /* only if a real NLA-track */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* only consider selected strips */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ // TODO: we can make strips have handles later on...
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ if (FrameOnMouseSide(side, strip->start, (float)CFRA))
+ {
+ /* init the 'extra' data for NLA strip handles first */
+ tdn->strip= strip;
+ tdn->val= strip->start;
+ tdn->handle= 0;
+
+ /* now, link the transform data up to this data */
+ td->val= &tdn->val;
+ td->ival= tdn->val;
+ td->extra= tdn;
+ td++;
+ tdn++;
+ }
+ if (FrameOnMouseSide(side, strip->end, (float)CFRA))
+ {
+ /* init the 'extra' data for NLA strip handles first */
+ tdn->strip= strip;
+ tdn->val= strip->end;
+ tdn->handle= 1;
+
+ /* now, link the transform data up to this data */
+ td->val= &tdn->val;
+ td->ival= tdn->val;
+ td->extra= tdn;
+ td++;
+ tdn++;
+ }
+ }
+ }
+ }
+ }
+
+ /* cleanup temp list */
+ BLI_freelistN(&anim_data);
+}
+
+/* ********************* ACTION EDITOR ****************** */
/* Called by special_aftertrans_update to make sure selected gp-frames replace
* any other gp-frames which may reside on that frame (that are not selected).
@@ -2744,19 +2874,6 @@ static void posttrans_action_clean (bAnimContext *ac, bAction *act)
/* ----------------------------- */
-/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
-static short FrameOnMouseSide(char side, float frame, float cframe)
-{
- /* both sides, so it doesn't matter */
- if (side == 'B') return 1;
-
- /* only on the named side */
- if (side == 'R')
- return (frame >= cframe) ? 1 : 0;
- else
- return (frame <= cframe) ? 1 : 0;
-}
-
/* fully select selected beztriples, but only include if it's on the right side of cfra */
static int count_fcurve_keys(FCurve *fcu, char side, float cfra)
{
@@ -3044,8 +3161,6 @@ static void createTransActionData(bContext *C, TransInfo *t)
/* ********************* GRAPH EDITOR ************************* */
-
-
/* Helper function for createTransGraphEditData, which is reponsible for associating
* source data with transform data
*/
@@ -3502,7 +3617,6 @@ void flushTransGraphData(TransInfo *t)
}
}
-
/* **************** IpoKey stuff, for Object TransData ********** */
/* while transforming */
@@ -4604,6 +4718,29 @@ void special_aftertrans_update(TransInfo *t)
/* make sure all F-Curves are set correctly */
ANIM_editkeyframes_refresh(&ac);
}
+ else if (t->spacetype == SPACE_NLA) {
+ SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first;
+ Scene *scene;
+ bAnimContext ac;
+
+ /* initialise relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ memset(&ac, 0, sizeof(bAnimContext));
+
+ scene= ac.scene= t->scene;
+ ob= ac.obact= OBACT;
+ ac.sa= t->sa;
+ ac.ar= t->ar;
+ ac.spacetype= (t->sa)? t->sa->spacetype : 0;
+ ac.regiontype= (t->ar)? t->ar->regiontype : 0;
+
+ if (ANIM_animdata_context_getdata(&ac) == 0)
+ return;
+
+ // XXX check on the calls below... we need some of these sanity checks
+ //synchronize_action_strips();
+ //ANIM_editkeyframes_refresh(&ac);
+ }
else if (t->obedit) {
// TRANSFORM_FIX_ME
// if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
@@ -4682,24 +4819,6 @@ void special_aftertrans_update(TransInfo *t)
}
}
-#if 0 // TRANSFORM_FIX_ME
- else if (t->spacetype == SPACE_NLA) {
- recalc_all_ipos(); // bad
- synchronize_action_strips();
-
- /* cleanup */
- for (base=t->scene->base.first; base; base=base->next)
- base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA);
-
- /* after transform, remove duplicate keyframes on a frame that resulted from transform */
- if ( (G.snla->flag & SNLA_NOTRANSKEYCULL)==0 &&
- ((cancelled == 0) || (duplicate)) )
- {
- posttrans_nla_clean(t);
- }
- }
-#endif
-
clear_trans_object_base_flags(t);
#if 0 // TRANSFORM_FIX_ME
@@ -4932,8 +5051,7 @@ void createTransData(bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_NLA) {
t->flag |= T_POINTS|T_2D_EDIT;
- // TRANSFORM_FIX_ME
- //createTransNlaData(C, t);
+ createTransNlaData(C, t);
}
else if (t->spacetype == SPACE_SEQ) {
t->flag |= T_POINTS|T_2D_EDIT;
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 171665c9282..4c9592fb27a 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -102,6 +102,8 @@
#include "BLI_editVert.h"
#include "BLI_rand.h"
+#include "RNA_access.h"
+
#include "WM_types.h"
#include "UI_resources.h"
@@ -299,61 +301,6 @@ void recalcData(TransInfo *t)
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
}
}
- }
- else if (t->spacetype == SPACE_NLA) {
- if (G.snla->lock) {
- for (base=G.scene->base.first; base; base=base->next) {
- if (base->flag & BA_HAS_RECALC_OB)
- base->object->recalc |= OB_RECALC_OB;
- if (base->flag & BA_HAS_RECALC_DATA)
- base->object->recalc |= OB_RECALC_DATA;
-
- if (base->object->recalc)
- base->object->ctime= -1234567.0f; // eveil!
-
- /* recalculate scale of selected nla-strips */
- if (base->object->nlastrips.first) {
- Object *bob= base->object;
- bActionStrip *strip;
-
- for (strip= bob->nlastrips.first; strip; strip= strip->next) {
- if (strip->flag & ACTSTRIP_SELECT) {
- float actlen= strip->actend - strip->actstart;
- float len= strip->end - strip->start;
-
- strip->scale= len / (actlen * strip->repeat);
- }
- }
- }
- }
-
- DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
- }
- else {
- for (base=G.scene->base.first; base; base=base->next) {
- /* recalculate scale of selected nla-strips */
- if (base->object && base->object->nlastrips.first) {
- Object *bob= base->object;
- bActionStrip *strip;
-
- for (strip= bob->nlastrips.first; strip; strip= strip->next) {
- if (strip->flag & ACTSTRIP_SELECT) {
- float actlen= strip->actend - strip->actstart;
- float len= strip->end - strip->start;
-
- /* prevent 'negative' scaling */
- if (len < 0) {
- SWAP(float, strip->start, strip->end);
- len= fabs(len);
- }
-
- /* calculate new scale */
- strip->scale= len / (actlen * strip->repeat);
- }
- }
- }
- }
- }
}
#endif
if (t->obedit) {
@@ -422,6 +369,47 @@ void recalcData(TransInfo *t)
}
}
+ else if (t->spacetype == SPACE_NLA) {
+ TransData *td= t->data;
+ int i;
+
+ /* for each point we've captured, look at its 'extra' data, which is basically a wrapper around the strip
+ * it is for + some extra storage for the values that get set, and use RNA to set this value (performing validation
+ * work so that we don't need to repeat it here)
+ */
+ for (i = 0; i < t->total; i++, td++)
+ {
+ if (td->extra)
+ {
+ TransDataNla *tdn= td->extra;
+ NlaStrip *strip= tdn->strip;
+
+ /* if we're just cancelling (i.e. the user aborted the transform),
+ * just restore the data by directly overwriting the values with the original
+ * ones (i.e. don't go through RNA), as we get some artifacts...
+ */
+ if (t->state == TRANS_CANCEL) {
+ /* write the value set by the transform tools to the appropriate property using RNA */
+ if (tdn->handle)
+ strip->end= tdn->val;
+ else
+ strip->start= tdn->val;
+ }
+ else {
+ PointerRNA strip_ptr;
+
+ /* make RNA-pointer */
+ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
+
+ /* write the value set by the transform tools to the appropriate property using RNA */
+ if (tdn->handle)
+ RNA_float_set(&strip_ptr, "end_frame", tdn->val);
+ else
+ RNA_float_set(&strip_ptr, "start_frame", tdn->val);
+ }
+ }
+ }
+ }
else if (t->obedit) {
if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
Curve *cu= t->obedit->data;
@@ -866,7 +854,7 @@ void postTrans (TransInfo *t)
if(sima->flag & SI_LIVE_UNWRAP)
ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
}
- else if(t->spacetype==SPACE_ACTION) {
+ else if(ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) {
if (t->customData)
MEM_freeN(t->customData);
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index e697b6dfa7d..de731ad7d95 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -607,6 +607,19 @@ void transform_keymap_for_space(struct wmWindowManager *wm, struct ListBase *key
km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
break;
+ case SPACE_NLA:
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", GKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
+
+ km= WM_keymap_add_item(keymap, "TFM_OT_transform", SKEY, KM_PRESS, 0, 0);
+ RNA_int_set(km->ptr, "mode", TFM_TIME_SCALE);
+ break;
case SPACE_NODE:
km= WM_keymap_add_item(keymap, "TFM_OT_translation", GKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 7e54045b5e4..a566f733978 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -269,6 +269,7 @@ typedef enum eAction_Flags {
/* flags for evaluation/editing */
ACT_MUTED = (1<<9),
ACT_PROTECTED = (1<<10),
+ ACT_DISABLED = (1<<11),
} eAction_Flags;
@@ -288,8 +289,10 @@ typedef struct bDopeSheet {
/* DopeSheet filter-flag */
typedef enum DOPESHEET_FILTERFLAG {
/* general filtering */
- ADS_FILTER_ONLYSEL = (1<<0),
- ADS_FILTER_ONLYDRIVERS = (1<<1),
+ ADS_FILTER_ONLYSEL = (1<<0), /* only include channels relating to selected data */
+
+ ADS_FILTER_ONLYDRIVERS = (1<<1), /* for 'Drivers' editor - only include Driver data from AnimData */
+ ADS_FILTER_ONLYNLA = (1<<2), /* for 'NLA' editor - only include NLA data from AnimData */
/* datatype-based filtering */
ADS_FILTER_NOSHAPEKEYS = (1<<6),
@@ -300,9 +303,11 @@ typedef enum DOPESHEET_FILTERFLAG {
ADS_FILTER_NOWOR = (1<<14),
ADS_FILTER_NOSCE = (1<<15),
+ /* NLA-specific filters */
+ ADS_FILTER_NLA_NOACT = (1<<20), /* if the AnimData block has no NLA data, don't include to just show Action-line */
+
/* combination filters (some only used at runtime) */
ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM|ADS_FILTER_NOMAT|ADS_FILTER_NOLAM|ADS_FILTER_NOCUR),
- ADS_FILTER_NLADUMMY = (ADS_FILTER_NOSHAPEKEYS|ADS_FILTER_NOOBDATA),
} DOPESHEET_FILTERFLAG;
/* DopeSheet general flags */
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index bf6b9bed5a1..a784adaf35f 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -108,6 +108,7 @@ enum {
FCM_GENERATOR_FN_TAN,
FCM_GENERATOR_FN_SQRT,
FCM_GENERATOR_FN_LN,
+ FCM_GENERATOR_FN_SINC,
} eFMod_Generator_Functions;
@@ -386,85 +387,93 @@ typedef struct AnimMapper {
/* ************************************************ */
/* NLA - Non-Linear Animation */
-// TODO: the concepts here still need to be refined to solve any unresolved items
-
-/* NLA Modifiers ---------------------------------- */
-
-/* These differ from F-Curve modifiers, as although F-Curve modifiers also operate on a
- * per-channel basis too (in general), they are part of the animation data itself, which
- * means that their effects are inherited by all of their users. In order to counteract this,
- * the modifiers here should be used to provide variation to pre-created motions only.
- */
/* NLA Strips ------------------------------------- */
/* NLA Strip (strip)
*
* A NLA Strip is a container for the reuse of Action data, defining parameters
- * to control the remapping of the Action data to some destination. Actions being
- * referenced by NLA-Strips SHOULD-NOT be editable, unless they were created in such
- * a way that results in very little mapping distortion (i.e. for layered animation only,
- * opposed to prebuilt 'blocks' which are quickly dumped into the NLA for crappymatic machima-type
- * stuff)
+ * to control the remapping of the Action data to some destination.
*/
typedef struct NlaStrip {
struct NlaStrip *next, *prev;
- bAction *act; /* Action that is referenced by this strip */
+ bAction *act; /* Action that is referenced by this strip (strip is 'user' of the action) */
AnimMapper *remap; /* Remapping info this strip (for tweaking correspondance of action with context) */
- ListBase modifiers; /* NLA Modifiers */
-
- ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */
+ ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out?
+ ListBase modifiers; /* F-Curve modifiers to be applied to the entire strip's referenced F-Curves */
float influence; /* Influence of strip */
- float act_time; /* Current 'time' within action being used */
+ float strip_time; /* Current 'time' within action being used (automatically evaluated, but can be overridden) */
float start, end; /* extents of the strip */
float actstart, actend; /* range of the action to use */
- float repeat; /* The number of times to repeat the action range (only when no F-Curves) */
- float scale; /* The amount the action range is scaled by (only when no F-Curves) */
+ float repeat; /* The number of times to repeat the action range (only when no F-Curves) */
+ float scale; /* The amount the action range is scaled by (only when no F-Curves) */
float blendin, blendout; /* strip blending length (only used when there are no F-Curves) */
- int blendmode; /* strip blending mode */
-
- int flag; /* settings */
+ short blendmode; /* strip blending mode (layer-based mixing) */
+ short extendmode; /* strip extrapolation mode (time-based mixing) */
- // umm... old unused cruft?
- int stride_axis; /* axis for stridebone stuff - 0=x, 1=y, 2=z */
- int pad;
-
- float actoffs; /* Offset within action, for cycles and striding (only set for ACT_USESTRIDE) */
- float stridelen; /* The stridelength (considered when flag & ACT_USESTRIDE) */
-
- char stridechannel[32]; /* Instead of stridelen, it uses an action channel */
- char offs_bone[32]; /* if repeat, use this bone/channel for defining offset */
+ short flag; /* settings */
+ short type; /* type of NLA strip */
} NlaStrip;
/* NLA Strip Blending Mode */
enum {
- NLASTRIPMODE_BLEND = 0,
- NLASTRIPMODE_ADD,
- NLASTRIPMODE_SUBTRACT,
-} eActStrip_Mode;
+ NLASTRIP_MODE_BLEND = 0,
+ NLASTRIP_MODE_ADD,
+ NLASTRIP_MODE_SUBTRACT,
+ NLASTRIP_MODE_MULTIPLY,
+} eNlaStrip_Blend_Mode;
+
+/* NLA Strip Extrpolation Mode */
+enum {
+ /* extend before first frame if no previous strips in track, and always hold+extend last frame */
+ NLASTRIP_EXTEND_HOLD = 0,
+ /* only hold+extend last frame */
+ NLASTRIP_EXTEND_HOLD_FORWARD,
+ /* don't contribute at all */
+ NLASTRIP_EXTEND_NOTHING,
+} eNlaStrip_Extrapolate_Mode;
/* NLA Strip Settings */
-// TODO: check on which of these are still useful...
enum {
- NLASTRIP_SELECT = (1<<0),
- NLASTRIP_USESTRIDE = (1<<1),
- NLASTRIP_BLENDTONEXT = (1<<2), /* Not implemented. Is not used anywhere */
- NLASTRIP_HOLDLASTFRAME = (1<<3),
- NLASTRIP_ACTIVE = (1<<4),
- NLASTRIP_LOCK_ACTION = (1<<5),
- NLASTRIP_MUTE = (1<<6),
- NLASTRIP_REVERSE = (1<<7), /* This has yet to be implemented. To indicate that a strip should be played backwards */
- NLASTRIP_CYCLIC_USEX = (1<<8),
- NLASTRIP_CYCLIC_USEY = (1<<9),
- NLASTRIP_CYCLIC_USEZ = (1<<10),
- NLASTRIP_AUTO_BLENDS = (1<<11),
- NLASTRIP_TWEAK = (1<<12), /* This strip is a tweaking strip (only set if owner track is a tweak track) */
-} eActionStrip_Flag;
+ /* UI selection flags */
+ /* NLA strip is the active one in the track (also indicates if strip is being tweaked) */
+ NLASTRIP_FLAG_ACTIVE = (1<<0),
+ /* NLA strip is selected for editing */
+ NLASTRIP_FLAG_SELECT = (1<<1),
+// NLASTRIP_FLAG_SELECT_L = (1<<2), // left handle selected
+// NLASTRIP_FLAG_SELECT_R = (1<<3), // right handle selected
+ /* NLA strip uses the same action that the action being tweaked uses (not set for the twaking one though) */
+ NLASTRIP_FLAG_TWEAKUSER = (1<<4),
+
+ /* controls driven by local F-Curves */
+ /* strip influence is controlled by local F-Curve */
+ NLASTRIP_FLAG_USR_INFLUENCE = (1<<5),
+ NLASTRIP_FLAG_USR_TIME = (1<<6),
+
+ /* playback flags (may be overriden by F-Curves) */
+ /* NLA strip blendin/out values are set automatically based on overlaps */
+ NLASTRIP_FLAG_AUTO_BLENDS = (1<<10),
+ /* NLA strip is played back in reverse order */
+ NLASTRIP_FLAG_REVERSE = (1<<11),
+ /* NLA strip is muted (i.e. doesn't contribute in any way) */
+ // TODO: this overlaps a lot with the functionality in track
+ NLASTRIP_FLAG_MUTED = (1<<12),
+ /* NLA strip length is synced to the length of the referenced action */
+ NLASTRIP_FLAG_SYNC_LENGTH = (1<<13),
+} eNlaStrip_Flag;
+
+/* NLA Strip Type */
+enum {
+ /* 'clip' - references an Action */
+ NLASTRIP_TYPE_CLIP = 0,
+ /* 'transition' - blends between the adjacent strips */
+ NLASTRIP_TYPE_TRANSITION,
+} eNlaStrip_Type;
/* NLA Tracks ------------------------------------- */
@@ -483,14 +492,12 @@ typedef struct NlaTrack {
int flag; /* settings for this track */
int index; /* index of the track in the stack (NOTE: not really useful, but we need a pad var anyways!) */
- char info[64]; /* short user-description of this track */
+ char name[64]; /* short user-description of this track */
} NlaTrack;
/* settings for track */
enum {
- /* track is the one that settings can be modified on (doesn't indicate
- * that it's for 'tweaking' though)
- */
+ /* track is the one that settings can be modified on, also indicates if track is being 'tweaked' */
NLATRACK_ACTIVE = (1<<0),
/* track is selected in UI for relevant editing operations */
NLATRACK_SELECTED = (1<<1),
@@ -500,10 +507,9 @@ enum {
NLATRACK_SOLO = (1<<3),
/* track's settings (and strips) cannot be edited (to guard against unwanted changes) */
NLATRACK_PROTECTED = (1<<4),
- /* strip is the 'last' one that should be evaluated, as the active action
- * is being used to tweak the animation of the strips up to here
- */
- NLATRACK_TWEAK = (1<<5),
+
+ /* track is not allowed to execute, usually as result of tweaking being enabled (internal flag) */
+ NLATRACK_DISABLED = (1<<10),
} eNlaTrack_Flag;
@@ -646,11 +652,15 @@ typedef struct AnimOverride {
* blocks may override local settings.
*
* This datablock should be placed immediately after the ID block where it is used, so that
- * the code which retrieves this data can do so in an easier manner. See blenkernel/internal/anim_sys.c for details.
+ * the code which retrieves this data can do so in an easier manner. See blenkernel/intern/anim_sys.c for details.
*/
typedef struct AnimData {
/* active action - acts as the 'tweaking track' for the NLA */
- bAction *action;
+ bAction *action;
+ /* temp-storage for the 'real' active action (i.e. the one used before the tweaking-action
+ * took over to be edited in the Animation Editors)
+ */
+ bAction *tmpact;
/* remapping-info for active action - should only be used if needed
* (for 'foreign' actions that aren't working correctly)
*/
@@ -676,11 +686,13 @@ enum {
ADT_NLA_SOLO_TRACK = (1<<0),
/* don't use NLA */
ADT_NLA_EVAL_OFF = (1<<1),
- /* don't execute drivers */
- ADT_DRIVERS_DISABLED = (1<<2),
+ /* NLA is being 'tweaked' (i.e. in EditMode) */
+ ADT_NLA_EDIT_ON = (1<<2),
/* drivers expanded in UI */
ADT_DRIVERS_COLLAPSED = (1<<10),
+ /* don't execute drivers */
+ ADT_DRIVERS_DISABLED = (1<<11),
} eAnimData_Flag;
/* Animation Data recalculation settings (to be set by depsgraph) */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 7391201776e..2219535bfd3 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -833,6 +833,7 @@ typedef struct Scene {
/* sce->flag */
#define SCE_DS_SELECTED (1<<0)
#define SCE_DS_COLLAPSED (1<<1)
+#define SCE_NLA_EDIT_ON (1<<2)
/* return flag next_object function */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 416acd7467e..28b5f882288 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -246,10 +246,11 @@ typedef struct SpaceNla {
short blockhandler[8];
- short menunr, lock;
short autosnap; /* this uses the same settings as autosnap for Action Editor */
short flag;
+ int pad;
+ struct bDopeSheet *ads;
View2D v2d; /* depricated, copied to region */
} SpaceNla;
@@ -711,8 +712,11 @@ enum {
#define IMS_INFILESLI 4
/* nla->flag */
+ // depreceated
#define SNLA_ALLKEYED (1<<0)
+ // depreceated
#define SNLA_ACTIVELAYERS (1<<1)
+
#define SNLA_DRAWTIME (1<<2)
#define SNLA_NOTRANSKEYCULL (1<<3)
#define SNLA_NODRAWCFRANUM (1<<4)
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 9b653bd924a..d4e952882ce 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -272,6 +272,8 @@ extern StructRNA RNA_MultiresModifier;
extern StructRNA RNA_MusgraveTexture;
extern StructRNA RNA_NandController;
extern StructRNA RNA_NearSensor;
+extern StructRNA RNA_NlaTrack;
+extern StructRNA RNA_NlaStrip;
extern StructRNA RNA_Node;
extern StructRNA RNA_NodeTree;
extern StructRNA RNA_NoiseTexture;
@@ -365,6 +367,7 @@ extern StructRNA RNA_Space;
extern StructRNA RNA_Space3DView;
extern StructRNA RNA_SpaceButtonsWindow;
extern StructRNA RNA_SpaceImageEditor;
+extern StructRNA RNA_SpaceNLA;
extern StructRNA RNA_SpaceOutliner;
extern StructRNA RNA_SpaceSequenceEditor;
extern StructRNA RNA_SpaceTextEditor;
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 75293d83346..eacf3a65c7d 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1846,6 +1846,7 @@ RNAProcessItem PROCESS_ITEMS[]= {
{"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh},
{"rna_meta.c", NULL, RNA_def_meta},
{"rna_modifier.c", NULL, RNA_def_modifier},
+ {"rna_nla.c", RNA_def_nla},
{"rna_nodetree.c", NULL, RNA_def_nodetree},
{"rna_object.c", "rna_object_api.c", RNA_def_object},
{"rna_object_force.c", NULL, RNA_def_object_force},
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 2ed47effec1..3469d716853 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -184,7 +184,7 @@ void rna_def_animdata(BlenderRNA *brna)
/* NLA */
prop= RNA_def_property(srna, "nla_tracks", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "nla_tracks", NULL);
- RNA_def_property_struct_type(prop, "UnknownType"); // XXX!
+ RNA_def_property_struct_type(prop, "NlaTrack");
RNA_def_property_ui_text(prop, "NLA Tracks", "NLA Tracks (i.e. Animation Layers).");
/* Action */
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 806219ec6bf..a1cd95c9d90 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -284,6 +284,7 @@ static void rna_def_fmodifier_generator_function(BlenderRNA *brna)
{2, "TAN", 0, "Tangent", ""},
{3, "SQRT", 0, "Square Root", ""},
{4, "LN", 0, "Natural Logarithm", ""},
+ {5, "SINC", 0, "Normalised Sine", "sin(x) / x"},
{0, NULL, 0, NULL, NULL}};
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 362217e3123..a3d5c4fe388 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -139,6 +139,7 @@ void RNA_def_material(struct BlenderRNA *brna);
void RNA_def_mesh(struct BlenderRNA *brna);
void RNA_def_meta(struct BlenderRNA *brna);
void RNA_def_modifier(struct BlenderRNA *brna);
+void RNA_def_nla(struct BlenderRNA *brna);
void RNA_def_nodetree(struct BlenderRNA *brna);
void RNA_def_object(struct BlenderRNA *brna);
void RNA_def_object_force(struct BlenderRNA *brna);
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
new file mode 100644
index 00000000000..4b5c14aab82
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -0,0 +1,349 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Blender Foundation (2009), Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "rna_internal.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#ifdef RNA_RUNTIME
+
+#include <stdio.h>
+#include <math.h>
+
+static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+
+ /* clamp value to lie within valid limits
+ * - cannot start past the end of the strip + some flexibility threshold
+ * - cannot start before the previous strip (if present) ends
+ * - minimum frame is -MAXFRAME so that we don't get clipping on frame 0
+ */
+ if (data->prev) {
+ CLAMP(value, data->prev->end, data->end-0.1f);
+ }
+ else {
+ CLAMP(value, -MAXFRAME, data->end);
+ }
+ data->start= value;
+}
+
+static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+ float len, actlen;
+
+ /* clamp value to lie within valid limits
+ * - must not have zero or negative length strip, so cannot start before the first frame
+ * + some minimum-strip-length threshold
+ * - cannot end later than the start of the next strip (if present)
+ */
+ if (data->next) {
+ CLAMP(value, data->start+0.1f, data->next->start);
+ }
+ else {
+ CLAMP(value, data->start+0.1f, MAXFRAME);
+ }
+ data->end= value;
+
+ /* calculate the lengths the strip and its action (if applicable) */
+ len= data->end - data->start;
+ actlen= data->actend - data->actstart;
+ if (IS_EQ(actlen, 0.0f)) actlen= 1.0f;
+
+ /* now, adjust the 'scale' setting to reflect this (so that this change can be valid) */
+ data->scale= len / ((actlen) * data->repeat);
+}
+
+static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+ float actlen, mapping;
+
+ /* set scale value */
+ CLAMP(value, 0.0001f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */
+ data->scale= value;
+
+ /* calculate existing factors */
+ actlen= data->actend - data->actstart;
+ if (IS_EQ(actlen, 0.0f)) actlen= 1.0f;
+ mapping= data->scale * data->repeat;
+
+ /* adjust endpoint of strip in response to this */
+ if (IS_EQ(mapping, 0.0f) == 0)
+ data->end = (actlen * mapping) + data->start;
+ else
+ printf("NlaStrip Set Scale Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat);
+}
+
+static void rna_NlaStrip_blend_in_set(PointerRNA *ptr, float value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+ float len;
+
+ /* blend-in is limited to the length of the strip, and also cannot overlap with blendout */
+ len= (data->end - data->start) - data->blendout;
+ CLAMP(value, 0, len);
+
+ data->blendin= value;
+}
+
+static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+ float len;
+
+ /* blend-out is limited to the length of the strip */
+ len= (data->end - data->start);
+ CLAMP(value, 0, len);
+
+ /* it also cannot overlap with blendin */
+ if ((len - value) < data->blendin)
+ value= len - data->blendin;
+
+ data->blendout= value;
+}
+
+static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+ CLAMP(value, -MAXFRAME, data->actend);
+ data->actstart= value;
+}
+
+static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+ CLAMP(value, data->actstart, MAXFRAME);
+ data->actend= value;
+}
+
+#else
+
+void rna_def_nlastrip(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* enum defs */
+ static EnumPropertyItem prop_type_items[] = {
+ {NLASTRIP_TYPE_CLIP, "CLIP", "Action Clip", "NLA Strip references some Action."},
+ {NLASTRIP_TYPE_TRANSITION, "TRANSITION", "Transition", "NLA Strip 'transitions' between adjacent strips."},
+ {0, NULL, NULL, NULL}};
+ static EnumPropertyItem prop_mode_blend_items[] = {
+ {NLASTRIP_MODE_BLEND, "BLEND", "Blend", "Results of strip and accumulated results are combined in ratio governed by influence."},
+ {NLASTRIP_MODE_ADD, "ADD", "Add", "Weighted result of strip is added to the accumlated results."},
+ {NLASTRIP_MODE_SUBTRACT, "SUBTRACT", "Subtract", "Weighted result of strip is removed from the accumlated results."},
+ {NLASTRIP_MODE_MULTIPLY, "MULITPLY", "Multiply", "Weighted result of strip is multiplied with the accumlated results."},
+ {0, NULL, NULL, NULL}};
+ static EnumPropertyItem prop_mode_extend_items[] = {
+ {NLASTRIP_EXTEND_NOTHING, "NOTHING", "Nothing", "Strip has no influence past its extents."},
+ {NLASTRIP_EXTEND_HOLD, "HOLD", "Hold", "Hold the first frame if no previous strips in track, and always hold last frame."},
+ {NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", "Hold Forward", "Only hold last frame."},
+ {0, NULL, NULL, NULL}};
+
+ /* struct definition */
+ srna= RNA_def_struct(brna, "NlaStrip", NULL);
+ RNA_def_struct_ui_text(srna, "NLA Strip", "A container referencing an existing Action.");
+ RNA_def_struct_ui_icon(srna, ICON_NLA); // XXX
+
+ /* Enums */
+ prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, prop_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Type of NLA Strip.");
+
+ prop= RNA_def_property(srna, "extrapolation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "extendmode");
+ RNA_def_property_enum_items(prop, prop_mode_extend_items);
+ RNA_def_property_ui_text(prop, "Extrapolation", "Action to take for gaps past the strip extents.");
+
+ prop= RNA_def_property(srna, "blending", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "blendmode");
+ RNA_def_property_enum_items(prop, prop_mode_blend_items);
+ RNA_def_property_ui_text(prop, "Blending", "Method used for combining strip's result with accumulated result.");
+
+ /* Strip extents */
+ prop= RNA_def_property(srna, "start_frame", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "start");
+ RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_start_frame_set", NULL);
+ RNA_def_property_ui_text(prop, "Start Frame", "");
+
+ prop= RNA_def_property(srna, "end_frame", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "end");
+ RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_end_frame_set", NULL);
+ RNA_def_property_ui_text(prop, "End Frame", "");
+
+ /* Blending */
+ prop= RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "blendin");
+ RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_in_set", NULL);
+ RNA_def_property_ui_text(prop, "Blend In", "Number of frames at start of strip to fade in influence.");
+
+ prop= RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "blendout");
+ RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_out_set", NULL);
+ RNA_def_property_ui_text(prop, "Blend Out", "");
+
+ prop= RNA_def_property(srna, "auto_blending", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_AUTO_BLENDS);
+ RNA_def_property_ui_text(prop, "Auto Blend In/Out", "Number of frames for Blending In/Out is automatically determined from overlapping strips.");
+
+ /* Action */
+ prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "act");
+ RNA_def_property_ui_text(prop, "Action", "Action referenced by this strip.");
+
+ /* Action extents */
+ prop= RNA_def_property(srna, "action_start_frame", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "actstart");
+ RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_start_frame_set", NULL);
+ RNA_def_property_ui_text(prop, "Action Start Frame", "");
+
+ prop= RNA_def_property(srna, "action_end_frame", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "actend");
+ RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_end_frame_set", NULL);
+ RNA_def_property_ui_text(prop, "Action End Frame", "");
+
+ /* Action Reuse */
+ prop= RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "repeat");
+ RNA_def_property_range(prop, 1.0f, 1000.0f); /* these limits have currently be chosen arbitarily, but could be extended (minimum should still be > 0 though) if needed... */
+ RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the ");
+
+ prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale");
+ RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_scale_set", NULL);
+ RNA_def_property_range(prop, 0.0001f, 1000.0f); /* these limits can be extended, but beyond this, we can get some crazy+annoying bugs due to numeric errors */
+ RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action.");
+
+ // TODO: strip's F-Curves?
+
+ /* Strip's F-Modifiers */
+ prop= RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FModifier");
+ RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting all the F-Curves in the referenced Action.");
+
+ /* Settings - Values necessary for evaluation */
+ prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Influence", "Amount the strip contributes to the current result.");
+
+ prop= RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate.");
+
+ prop= RNA_def_property(srna, "animated_influence", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE);
+ RNA_def_property_ui_text(prop, "Animated Influence", "Influence setting is controlled by an F-Curve rather than automatically determined.");
+
+ prop= RNA_def_property(srna, "animated_time", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE);
+ RNA_def_property_ui_text(prop, "Animated Strip Time", "Strip time is controlled by an F-Curve rather than automatically determined.");
+
+ /* settings */
+ prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_ACTIVE);
+ RNA_def_property_ui_text(prop, "Active", "NLA Strip is active.");
+
+ prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_SELECT);
+ RNA_def_property_ui_text(prop, "Selected", "NLA Strip is selected.");
+
+ prop= RNA_def_property(srna, "muted", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_MUTED);
+ RNA_def_property_ui_text(prop, "Muted", "NLA Strip is not evaluated.");
+
+ prop= RNA_def_property(srna, "reversed", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_REVERSE);
+ RNA_def_property_ui_text(prop, "Reversed", "NLA Strip is played back in reverse order (only when timing is automatically determined).");
+
+ // TODO:
+ // - sync length
+}
+
+void rna_def_nlatrack(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "NlaTrack", NULL);
+ RNA_def_struct_ui_text(srna, "NLA Track", "A animation layer containing Actions referenced as NLA strips.");
+ RNA_def_struct_ui_icon(srna, ICON_NLA);
+
+ /* strips collection */
+ prop= RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "NlaStrip");
+ RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips on this NLA-track.");
+
+ /* name property */
+ prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "");
+ RNA_def_struct_name_property(srna, prop);
+
+ /* settings */
+ prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_ACTIVE);
+ RNA_def_property_ui_text(prop, "Active", "NLA Track is active.");
+
+ prop= RNA_def_property(srna, "solo", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SOLO);
+ RNA_def_property_ui_text(prop, "Solo", "NLA Track is evaluated itself (i.e. active Action and all other NLA Tracks in the same AnimData block are disabled).");
+
+ prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SELECTED);
+ RNA_def_property_ui_text(prop, "Selected", "NLA Track is selected.");
+
+ prop= RNA_def_property(srna, "muted", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_MUTED);
+ RNA_def_property_ui_text(prop, "Muted", "NLA Track is not evaluated.");
+
+ prop= RNA_def_property(srna, "locked", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_PROTECTED);
+ RNA_def_property_ui_text(prop, "Locked", "NLA Track is locked.");
+}
+
+/* --------- */
+
+void RNA_def_nla(BlenderRNA *brna)
+{
+ rna_def_nlatrack(brna);
+ rna_def_nlastrip(brna);
+}
+
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index ff9777d283e..a17cc1aca3d 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1075,29 +1075,6 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Pose Mode", "Object with armature data is in pose mode.");
- // XXX this stuff should be moved to AnimData...
-/*
- prop= RNA_def_property(srna, "nla_disable_path", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_DISABLE_PATH);
- RNA_def_property_ui_text(prop, "NLA Disable Path", "Disable path temporally, for editing cycles.");
-
- prop= RNA_def_property(srna, "nla_collapsed", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_NLA_COLLAPSED);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "NLA Collapsed", "");
-
- prop= RNA_def_property(srna, "nla_override", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "nlaflag", OB_NLA_OVERRIDE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "NLA Override", "");
-
- prop= RNA_def_property(srna, "nla_strips", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nlastrips", NULL);
- RNA_def_property_struct_type(prop, "UnknownType");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "NLA Strips", "NLA strips of the object.");
-*/
-
/* shape keys */
prop= RNA_def_property(srna, "shape_key_lock", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 41acc458cd9..78c49a493f4 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -111,10 +111,10 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr)
/*case SPACE_SOUND:
return &RNA_SpaceAudioWindow;
case SPACE_ACTION:
- return &RNA_SpaceDopeSheetEditor;
+ return &RNA_SpaceDopeSheetEditor;*/
case SPACE_NLA:
- return &RNA_SpaceNLAEditor;
- case SPACE_SCRIPT:
+ return &RNA_SpaceNLA;
+ /*case SPACE_SCRIPT:
return &RNA_SpaceScriptsWindow;
case SPACE_TIME:
return &RNA_SpaceTimeline;
@@ -868,6 +868,27 @@ static void rna_def_space_text(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Replace Text", "Text to replace selected text with using the replace tool.");
}
+static void rna_def_space_nla(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "SpaceNLA", "Space");
+ RNA_def_struct_sdna(srna, "SpaceNla");
+ RNA_def_struct_ui_text(srna, "Space Nla Editor", "NLA editor space data.");
+
+ /* display */
+ prop= RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_DRAWTIME);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, only set with operator
+ RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames.");
+
+ prop= RNA_def_property(srna, "show_cframe_indicator", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NODRAWCFRANUM);
+ RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line.");
+
+}
+
void RNA_def_space(BlenderRNA *brna)
{
rna_def_space(brna);
@@ -878,6 +899,7 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_background_image(brna);
rna_def_space_3dview(brna);
rna_def_space_buttons(brna);
+ rna_def_space_nla(brna);
}
#endif
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp
deleted file mode 100644
index 80165548ff2..00000000000
--- a/source/gameengine/Converter/BL_ModifierDeformer.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifdef WIN32
-#pragma warning (disable : 4786)
-#endif //WIN32
-
-#include "MEM_guardedalloc.h"
-#include "BL_ModifierDeformer.h"
-#include "GEN_Map.h"
-#include "STR_HashedString.h"
-#include "RAS_IPolygonMaterial.h"
-#include "BL_SkinMeshObject.h"
-#include "PHY_IGraphicController.h"
-
-//#include "BL_ArmatureController.h"
-#include "DNA_armature_types.h"
-#include "DNA_action_types.h"
-#include "DNA_key_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_ipo_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_scene_types.h"
-#include "BKE_armature.h"
-#include "BKE_action.h"
-#include "BKE_key.h"
-#include "BKE_ipo.h"
-#include "MT_Point3.h"
-
-extern "C"{
- #include "BKE_customdata.h"
- #include "BKE_DerivedMesh.h"
- #include "BKE_lattice.h"
- #include "BKE_modifier.h"
-}
- #include "BKE_utildefines.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_arithb.h"
-
-#define __NLA_DEFNORMALS
-//#undef __NLA_DEFNORMALS
-
-
-BL_ModifierDeformer::~BL_ModifierDeformer()
-{
- if (m_dm) {
- // deformedOnly is used as a user counter
- if (--m_dm->deformedOnly == 0) {
- m_dm->needsFree = 1;
- m_dm->release(m_dm);
- }
- }
-};
-
-RAS_Deformer *BL_ModifierDeformer::GetReplica()
-{
- BL_ModifierDeformer *result;
-
- result = new BL_ModifierDeformer(*this);
- result->ProcessReplica();
- return result;
-}
-
-void BL_ModifierDeformer::ProcessReplica()
-{
- /* Note! - This is not inherited from PyObjectPlus */
- BL_ShapeDeformer::ProcessReplica();
- if (m_dm)
- // by default try to reuse mesh, deformedOnly is used as a user count
- m_dm->deformedOnly++;
- // this will force an update and if the mesh cannot be reused, a new one will be created
- m_lastModifierUpdate = -1;
-}
-
-bool BL_ModifierDeformer::HasCompatibleDeformer(Object *ob)
-{
- if (!ob->modifiers.first)
- return false;
- // soft body cannot use mesh modifiers
- if ((ob->gameflag & OB_SOFT_BODY) != 0)
- return false;
- ModifierData* md;
- for (md = (ModifierData*)ob->modifiers.first; md; md = (ModifierData*)md->next) {
- if (modifier_dependsOnTime(md))
- continue;
- if (!(md->mode & eModifierMode_Realtime))
- continue;
- return true;
- }
- return false;
-}
-
-bool BL_ModifierDeformer::Update(void)
-{
- bool bShapeUpdate = BL_ShapeDeformer::Update();
-
- if (bShapeUpdate || m_lastModifierUpdate != m_gameobj->GetLastFrame()) {
- // static derived mesh are not updated
- if (m_dm == NULL || m_bDynamic) {
- /* execute the modifiers */
- Object* blendobj = m_gameobj->GetBlendObject();
- /* hack: the modifiers require that the mesh is attached to the object
- It may not be the case here because of replace mesh actuator */
- Mesh *oldmesh = (Mesh*)blendobj->data;
- blendobj->data = m_bmesh;
- /* execute the modifiers */
- DerivedMesh *dm = mesh_create_derived_no_virtual(m_scene, blendobj, m_transverts, CD_MASK_MESH);
- /* restore object data */
- blendobj->data = oldmesh;
- /* free the current derived mesh and replace, (dm should never be NULL) */
- if (m_dm != NULL) {
- // HACK! use deformedOnly as a user counter
- if (--m_dm->deformedOnly == 0) {
- m_dm->needsFree = 1;
- m_dm->release(m_dm);
- }
- }
- m_dm = dm;
- // get rid of temporary data
- m_dm->needsFree = 0;
- m_dm->release(m_dm);
- // HACK! use deformedOnly as a user counter
- m_dm->deformedOnly = 1;
- /* update the graphic controller */
- PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController();
- if (ctrl) {
- float min_r[3], max_r[3];
- INIT_MINMAX(min_r, max_r);
- m_dm->getMinMax(m_dm, min_r, max_r);
- ctrl->setLocalAabb(min_r, max_r);
- }
- }
- m_lastModifierUpdate=m_gameobj->GetLastFrame();
- bShapeUpdate = true;
- }
- return bShapeUpdate;
-}
-
-bool BL_ModifierDeformer::Apply(RAS_IPolyMaterial *mat)
-{
- if (!Update())
- return false;
-
- // drawing is based on derived mesh, must set it in the mesh slots
- int nmat = m_pMeshObject->NumMaterials();
- for (int imat=0; imat<nmat; imat++) {
- RAS_MeshMaterial *mmat = m_pMeshObject->GetMeshMaterial(imat);
- RAS_MeshSlot **slot = mmat->m_slots[(void*)m_gameobj];
- if(!slot || !*slot)
- continue;
- (*slot)->m_pDerivedMesh = m_dm;
- }
- return true;
-}
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.h b/source/gameengine/Converter/BL_ModifierDeformer.h
deleted file mode 100644
index b09cc2087ca..00000000000
--- a/source/gameengine/Converter/BL_ModifierDeformer.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef BL_MODIFIERDEFORMER
-#define BL_MODIFIERDEFORMER
-
-#ifdef WIN32
-#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
-#endif //WIN32
-
-#include "BL_ShapeDeformer.h"
-#include "BL_DeformableGameObject.h"
-#include <vector>
-
-struct DerivedMesh;
-struct Object;
-
-class BL_ModifierDeformer : public BL_ShapeDeformer
-{
-public:
- static bool HasCompatibleDeformer(Object *ob);
-
-
- BL_ModifierDeformer(BL_DeformableGameObject *gameobj,
- Scene *scene,
- Object *bmeshobj,
- BL_SkinMeshObject *mesh)
- :
- BL_ShapeDeformer(gameobj,bmeshobj, mesh),
- m_lastModifierUpdate(-1),
- m_scene(scene),
- m_dm(NULL)
- {
- m_recalcNormal = false;
- };
-
- /* this second constructor is needed for making a mesh deformable on the fly. */
- BL_ModifierDeformer(BL_DeformableGameObject *gameobj,
- struct Scene *scene,
- struct Object *bmeshobj_old,
- struct Object *bmeshobj_new,
- class BL_SkinMeshObject *mesh,
- bool release_object,
- BL_ArmatureObject* arma = NULL)
- :
- BL_ShapeDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, false, arma),
- m_lastModifierUpdate(-1),
- m_scene(scene),
- m_dm(NULL)
- {
- };
-
- virtual void ProcessReplica();
- virtual RAS_Deformer *GetReplica();
- virtual ~BL_ModifierDeformer();
- virtual bool UseVertexArray()
- {
- return false;
- }
-
- bool Update (void);
- bool Apply(RAS_IPolyMaterial *mat);
- void ForceUpdate()
- {
- m_lastModifierUpdate = -1.0;
- };
- virtual struct DerivedMesh* GetFinalMesh()
- {
- return m_dm;
- }
-
-
-protected:
- double m_lastModifierUpdate;
- Scene *m_scene;
- DerivedMesh *m_dm;
-
-};
-
-#endif
-
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp
deleted file mode 100644
index 524d957a80c..00000000000
--- a/source/gameengine/Ketsji/KX_PythonSeq.cpp
+++ /dev/null
@@ -1,453 +0,0 @@
-/**
- * $Id:
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: none of this file.
- *
- * Contributor(s): Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- * Readonly sequence wrapper for lookups on logic bricks
- */
-
-
-#include "KX_PythonSeq.h"
-#include "KX_GameObject.h"
-#include "SCA_ISensor.h"
-#include "SCA_IController.h"
-#include "SCA_IActuator.h"
-
-
-PyObject *KX_PythonSeq_CreatePyObject( PyObject *base, short type )
-{
- KX_PythonSeq *seq = PyObject_NEW( KX_PythonSeq, &KX_PythonSeq_Type);
- seq->base = base;
- Py_INCREF(base); /* so we can always access to check if its valid */
- seq->type = type;
- seq->iter = -1; /* init */
- return (PyObject *)seq;
- }
-
- static void KX_PythonSeq_dealloc( KX_PythonSeq * self )
-{
- Py_DECREF(self->base);
- PyObject_DEL( self );
-}
-
-static Py_ssize_t KX_PythonSeq_len( PyObject * self )
-{
- PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
-
- if(self_plus==NULL) {
- PyErr_SetString(PyExc_SystemError, "len(seq): "BGE_PROXY_ERROR_MSG);
- return -1;
- }
-
- switch(((KX_PythonSeq *)self)->type) {
- case KX_PYGENSEQ_CONT_TYPE_SENSORS:
- return ((SCA_IController *)self_plus)->GetLinkedSensors().size();
- case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
- return ((SCA_IController *)self_plus)->GetLinkedActuators().size();
- case KX_PYGENSEQ_OB_TYPE_SENSORS:
- return ((KX_GameObject *)self_plus)->GetSensors().size();
- case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
- return ((KX_GameObject *)self_plus)->GetControllers().size();
- case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
- return ((KX_GameObject *)self_plus)->GetActuators().size();
- default:
- /* Should never happen */
- PyErr_SetString(PyExc_SystemError, "invalid type, internal error");
- return -1;
- }
-}
-
-static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index)
-{
- PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
-
- if(self_plus==NULL) {
- PyErr_SetString(PyExc_SystemError, "val = seq[i]: "BGE_PROXY_ERROR_MSG);
- return NULL;
- }
-
- switch(((KX_PythonSeq *)self)->type) {
- case KX_PYGENSEQ_CONT_TYPE_SENSORS:
- {
- vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors();
- if(index<0) index += linkedsensors.size();
- if(index<0 || index>= linkedsensors.size()) {
- PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
- return NULL;
- }
- return linkedsensors[index]->GetProxy();
- }
- case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
- {
- vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators();
- if(index<0) index += linkedactuators.size();
- if(index<0 || index>= linkedactuators.size()) {
- PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
- return NULL;
- }
- return linkedactuators[index]->GetProxy();
- }
- case KX_PYGENSEQ_OB_TYPE_SENSORS:
- {
- SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors();
- if(index<0) index += linkedsensors.size();
- if(index<0 || index>= linkedsensors.size()) {
- PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
- return NULL;
- }
- return linkedsensors[index]->GetProxy();
- }
- case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
- {
- SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers();
- if(index<0) index += linkedcontrollers.size();
- if(index<0 || index>= linkedcontrollers.size()) {
- PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
- return NULL;
- }
- return linkedcontrollers[index]->GetProxy();
- }
- case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
- {
- SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators();
- if(index<0) index += linkedactuators.size();
- if(index<0 || index>= linkedactuators.size()) {
- PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
- return NULL;
- }
- return linkedactuators[index]->GetProxy();
- }
- }
-
- PyErr_SetString(PyExc_SystemError, "invalid sequence type, this is a bug");
- return NULL;
-}
-
-static PyObjectPlus * KX_PythonSeq_subscript__internal(PyObject *self, char *key)
-{
- PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
-
- switch(((KX_PythonSeq *)self)->type) {
- case KX_PYGENSEQ_CONT_TYPE_SENSORS:
- {
- vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors();
- SCA_ISensor* sensor;
- for (unsigned int index=0;index<linkedsensors.size();index++) {
- sensor = linkedsensors[index];
- if (sensor->GetName() == key)
- return static_cast<PyObjectPlus *>(sensor);
-
- }
- break;
- }
- case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
- {
- vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators();
- SCA_IActuator* actuator;
- for (unsigned int index=0;index<linkedactuators.size();index++) {
- actuator = linkedactuators[index];
- if (actuator->GetName() == key)
- return static_cast<PyObjectPlus *>(actuator);
- }
- break;
- }
- case KX_PYGENSEQ_OB_TYPE_SENSORS:
- {
- SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors();
- SCA_ISensor *sensor;
- for (unsigned int index=0;index<linkedsensors.size();index++) {
- sensor= linkedsensors[index];
- if (sensor->GetName() == key)
- return static_cast<PyObjectPlus *>(sensor);
- }
- break;
- }
- case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
- {
- SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers();
- SCA_IController *controller;
- for (unsigned int index=0;index<linkedcontrollers.size();index++) {
- controller= linkedcontrollers[index];
- if (controller->GetName() == key)
- return static_cast<PyObjectPlus *>(controller);
- }
- break;
- }
- case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
- {
- SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators();
- SCA_IActuator *actuator;
- for (unsigned int index=0;index<linkedactuators.size();index++) {
- actuator= linkedactuators[index];
- if (actuator->GetName() == key)
- return static_cast<PyObjectPlus *>(actuator);
- }
- break;
- }
- }
-
- return NULL;
-}
-
-
-static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key)
-{
- PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
-
- if(self_plus==NULL) {
- PyErr_SetString(PyExc_SystemError, "val = seq[key], KX_PythonSeq: "BGE_PROXY_ERROR_MSG);
- return NULL;
- }
-
- if (PyInt_Check(key)) {
- return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key ));
- }
- else if ( PyString_Check(key) ) {
- char *name = PyString_AsString(key);
- PyObjectPlus *ret = KX_PythonSeq_subscript__internal(self, name);
-
- if(ret) {
- return ret->GetProxy();
- } else {
- PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name);
- return NULL;
- }
- }
- else {
- PyErr_SetString( PyExc_TypeError, "expected a string or an index" );
- return NULL;
- }
-}
-
-
-static int KX_PythonSeq_contains(PyObject *self, PyObject *key)
-{
- PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
-
- if(self_plus==NULL) {
- PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: "BGE_PROXY_ERROR_MSG);
- return -1;
- }
- if(!PyString_Check(key)) {
- PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: key must be a string");
- return -1;
- }
-
- if(KX_PythonSeq_subscript__internal(self, PyString_AsString(key)))
- return 1;
-
- return 0;
-}
-
-/* Matches python dict.get(key, [default]) */
-PyObject* KX_PythonSeq_get(PyObject * self, PyObject *args)
-{
- char *key;
- PyObject* def = Py_None;
- PyObjectPlus* ret_plus;
-
- if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
- return NULL;
-
- if((ret_plus = KX_PythonSeq_subscript__internal(self, key)))
- return ret_plus->GetProxy();
-
- Py_INCREF(def);
- return def;
-}
-
-PySequenceMethods KX_PythonSeq_as_sequence = {
- NULL, /* Cant set the len otherwise it can evaluate as false */
- NULL, /* sq_concat */
- NULL, /* sq_repeat */
- NULL, /* sq_item */
- NULL, /* sq_slice */
- NULL, /* sq_ass_item */
- NULL, /* sq_ass_slice */
- (objobjproc)KX_PythonSeq_contains, /* sq_contains */
-};
-
-static PyMappingMethods KX_PythonSeq_as_mapping = {
- KX_PythonSeq_len, /* mp_length */
- KX_PythonSeq_subscript, /* mp_subscript */
- 0, /* mp_ass_subscript */
-};
-
-PyMethodDef KX_PythonSeq_methods[] = {
- // dict style access for props
- {"get",(PyCFunction) KX_PythonSeq_get, METH_VARARGS},
- {NULL,NULL} //Sentinel
-};
-
-/*
- * Initialize the interator index
- */
-
-static PyObject *KX_PythonSeq_getIter(KX_PythonSeq *self)
-{
- if(BGE_PROXY_REF(self->base)==NULL) {
- PyErr_SetString(PyExc_SystemError, "for i in seq: "BGE_PROXY_ERROR_MSG);
- return NULL;
- }
-
- /* create a new iterator if were alredy using this one */
- if (self->iter == -1) {
- self->iter = 0;
- Py_INCREF(self);
- return (PyObject *)self;
- } else {
- return KX_PythonSeq_CreatePyObject(self->base, self->type);
- }
- }
-
-
-/*
- * Return next KX_PythonSeq iter.
- */
-
-static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self)
-{
- PyObject *object = KX_PythonSeq_getIndex((PyObject *)self, self->iter);
-
- self->iter++;
- if( object==NULL ) {
- self->iter= -1; /* for reuse */
- PyErr_SetString(PyExc_StopIteration, "iterator at end");
- }
- return object; /* can be NULL for end of iterator */
-}
-
-
-static int KX_PythonSeq_compare( KX_PythonSeq * a, KX_PythonSeq * b ) /* TODO - python3.x wants richcmp */
-{
- return ( a->type == b->type && a->base == b->base) ? 0 : -1;
-}
-
-/*
- * repr function
- * convert to a list and get its string value
- */
-static PyObject *KX_PythonSeq_repr( KX_PythonSeq * self )
-{
- PyObject *list = PySequence_List((PyObject *)self);
- PyObject *repr = PyObject_Repr(list);
- Py_DECREF(list);
- return repr;
-}
-
-
-/*****************************************************************************/
-/* Python KX_PythonSeq_Type structure definition: */
-/*****************************************************************************/
-PyTypeObject KX_PythonSeq_Type = {
-#if (PY_VERSION_HEX >= 0x02060000)
- PyVarObject_HEAD_INIT(NULL, 0)
-#else
- /* python 2.5 and below */
- PyObject_HEAD_INIT( NULL ) /* required py macro */
- 0, /* ob_size */
-#endif
- /* For printing, in format "<module>.<name>" */
- "KX_PythonSeq", /* char *tp_name; */
- sizeof( KX_PythonSeq ), /* int tp_basicsize; */
- 0, /* tp_itemsize; For allocation */
-
- /* Methods to implement standard operations */
-
- ( destructor ) KX_PythonSeq_dealloc, /* destructor tp_dealloc; */
- NULL, /* printfunc tp_print; */
- NULL, /* getattrfunc tp_getattr; */
- NULL, /* setattrfunc tp_setattr; */
-#if PY_VERSION_HEX >= 0x03000000 // TODO - richcmp
- NULL,
-#else
- ( cmpfunc ) KX_PythonSeq_compare, /* cmpfunc tp_compare; */
-#endif
- ( reprfunc ) KX_PythonSeq_repr, /* reprfunc tp_repr; */
-
- /* Method suites for standard classes */
-
- NULL, /* PyNumberMethods *tp_as_number; */
- &KX_PythonSeq_as_sequence, /* PySequenceMethods *tp_as_sequence; */
- &KX_PythonSeq_as_mapping, /* PyMappingMethods *tp_as_mapping; */
-
- /* More standard operations (here for binary compatibility) */
-
- NULL, /* hashfunc tp_hash; */
- NULL, /* ternaryfunc tp_call; */
- NULL, /* reprfunc tp_str; */
- NULL, /* getattrofunc tp_getattro; */
- NULL, /* setattrofunc tp_setattro; */
-
- /* Functions to access object as input/output buffer */
- NULL, /* PyBufferProcs *tp_as_buffer; */
-
- /*** Flags to define presence of optional/expanded features ***/
- Py_TPFLAGS_DEFAULT, /* long tp_flags; */
-
- NULL, /* char *tp_doc; Documentation string */
- /*** Assigned meaning in release 2.0 ***/
- /* call function for all accessible objects */
- NULL, /* traverseproc tp_traverse; */
-
- /* delete references to contained objects */
- NULL, /* inquiry tp_clear; */
-
- /*** Assigned meaning in release 2.1 ***/
- /*** rich comparisons ***/
- NULL, /* richcmpfunc tp_richcompare; */
-
- /*** weak reference enabler ***/
- 0, /* long tp_weaklistoffset; */
-
- /*** Added in release 2.2 ***/
- /* Iterators */
- ( getiterfunc) KX_PythonSeq_getIter, /* getiterfunc tp_iter; */
- ( iternextfunc ) KX_PythonSeq_nextIter, /* iternextfunc tp_iternext; */
-
- /*** Attribute descriptor and subclassing stuff ***/
- KX_PythonSeq_methods, /* struct PyMethodDef *tp_methods; */
- NULL, /* struct PyMemberDef *tp_members; */
- NULL, /* struct PyGetSetDef *tp_getset; */
- NULL, /* struct _typeobject *tp_base; */
- NULL, /* PyObject *tp_dict; */
- NULL, /* descrgetfunc tp_descr_get; */
- NULL, /* descrsetfunc tp_descr_set; */
- 0, /* long tp_dictoffset; */
- NULL, /* initproc tp_init; */
- NULL, /* allocfunc tp_alloc; */
- NULL, /* newfunc tp_new; */
- /* Low-level free-memory routine */
- NULL, /* freefunc tp_free; */
- /* For PyObject_IS_GC */
- NULL, /* inquiry tp_is_gc; */
- NULL, /* PyObject *tp_bases; */
- /* method resolution order */
- NULL, /* PyObject *tp_mro; */
- NULL, /* PyObject *tp_cache; */
- NULL, /* PyObject *tp_subclasses; */
- NULL, /* PyObject *tp_weaklist; */
- NULL
-};
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.h b/source/gameengine/Ketsji/KX_PythonSeq.h
deleted file mode 100644
index 15a016224a9..00000000000
--- a/source/gameengine/Ketsji/KX_PythonSeq.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * $Id:
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- * Readonly sequence wrapper for lookups on logic bricks
- */
-
-#ifndef _adr_py_seq_h_ // only process once,
-#define _adr_py_seq_h_ // even if multiply included
-
-#include "PyObjectPlus.h"
-
-// -------------------------
-enum KX_PYGENSEQ_TYPE {
- KX_PYGENSEQ_CONT_TYPE_SENSORS,
- KX_PYGENSEQ_CONT_TYPE_ACTUATORS,
- KX_PYGENSEQ_OB_TYPE_SENSORS,
- KX_PYGENSEQ_OB_TYPE_CONTROLLERS,
- KX_PYGENSEQ_OB_TYPE_ACTUATORS
-};
-
-/* The Main PyType Object defined in Main.c */
-extern PyTypeObject KX_PythonSeq_Type;
-
-#define BPy_KX_PythonSeq_Check(v) \
- ((v)->ob_type == &KX_PythonSeq_Type)
-
-typedef struct {
- PyObject_VAR_HEAD
- PyObject *base;
- short type;
- short iter;
-} KX_PythonSeq;
-
-PyObject *KX_PythonSeq_CreatePyObject(PyObject *base, short type);
-
-#endif // _adr_py_seq_h_
diff --git a/source/gameengine/PyDoc/API_intro.py b/source/gameengine/PyDoc/API_intro.py
deleted file mode 100644
index 578b56eb2b0..00000000000
--- a/source/gameengine/PyDoc/API_intro.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# This is not a real module, it's simply an introductory text.
-
-"""
-The Blender Game Engine Python API Reference
-============================================
-
- See U{release notes<http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.49/Game_Engine>} for updates, changes and new functionality in the Game Engine Python API.
-
- Blender Game Engine Modules:
- ----------------------------
-
- Modules that include methods for accessing GameEngine data and functions.
-
- - L{GameLogic} utility functons for game logic.
- - L{GameKeys} keyboard input and event conversion.
- - L{Rasterizer} display and rendering.
- - L{GameTypes} contains all the python types spesific to the GameEngine.
-
- Undocumented modules:
- ---------------------
- - VideoTexture
- - PhysicsConstraints
-
- Additional Modules:
- -------------------
-
- These modules have no GameEngine spesific functionality but are useful in many cases.
-
- - L{Mathutils}
- - L{Geometry}
- - L{BGL}
-
-
-Introduction:
-=============
-
- This reference documents the Blender Python API, a growing collection of
- Python modules (libraries) that give access to part of the program's internal
- data and functions.
-
- Through scripting Blender can be extended in real-time via
- U{Python <www.python.org>}, an impressive high level, multi-paradigm, open
- source language. Newcomers are recommended to start with the tutorial that
- comes with it.
-
- This opens many interesting possibilities not available with logic bricks.
-
- Game Engine API Stability:
- --------------------------
-
- When writing python scripts there are a number of situations you should avoid to prevent crashes or unstable behavior.
- While the API tries to prevent problems there are some situations where error checking would be too time consuming.
-
- Known cases:
- - Memory Limits.
-
- There is nothing stopping you from filling a list or making a string so big that that causes blender to run out of memory, in this case python should rasie a MemoryError, but its likely blender will crash before this point.
-
- - Accessing any data that has been freed.
-
- For instance accessing a KX_GameObject after its End Object actuator runs.
- This will cause a SystemError, however for L{KX_MeshProxy}, L{KX_VertexProxy} and L{KX_VertexProxy} it will crash the blender game engine.
-
- See: L{GameTypes.PyObjectPlus.invalid} which many types inherit.
-
- - Mixing L{KX_GameObject} between scenes.
-
- For instance tracking/parenting an L{KX_GameObject} object to an object from other scene.
-
- External Modules:
- -----------------
-
- Since 2.49 support for importing modules has been added.
-
- This allows you to import any blender textblock with a .py extension.
-
- External python scripts may be imported as modules when the script is in the same directory as the blend file.
-
- The current blend files path is included in the sys.path for loading modules.
- All linked libraries will also be included so you can be sure when linking in assets from another blend file the scripts will load too.
-
- A note to newbie script writers:
- --------------------------------
-
- Interpreted languages are known to be much slower than compiled code, but for
- many applications the difference is negligible or acceptable. Also, with
- profiling (or even simple direct timing with L{Blender.sys.time<Sys.time>}) to
- identify slow areas and well thought optimizations, the speed can be
- I{considerably} improved in many cases. Try some of the best BPython scripts
- to get an idea of what can be done, you may be surprised.
-
-@author: The Blender Python Team
-@requires: Blender 2.49 or newer.
-@version: 2.49
-@see: U{www.blender.org<http://www.blender.org>}: documentation and forum
-@see: U{blenderartists.org<http://blenderartists.org>}: user forum
-@see: U{projects.blender.org<http://projects.blender.org>}
-@see: U{www.python.org<http://www.python.org>}
-@see: U{www.python.org/doc<http://www.python.org/doc>}
-@see: U{Blending into Python<en.wikibooks.org/wiki/Blender_3D:_Blending_Into_Python>}: User contributed documentation, featuring a blender/python cookbook with many examples.
-
-@note: the official version of this reference guide is only updated for each
- new Blender release. But you can build the current SVN
- version yourself: install epydoc, grab all files in the
- source/gameengine/PyDoc/ folder of Blender's SVN and use the
- epy_docgen.sh script also found there to generate the html docs.
- Naturally you will also need a recent Blender binary to try the new
- features. If you prefer not to compile it yourself, there is a testing
- builds forum at U{blender.org<http://www.blender.org>}.
-"""
diff --git a/source/gameengine/SceneGraph/SG_DList.h b/source/gameengine/SceneGraph/SG_DList.h
deleted file mode 100644
index 7bef13cc9e3..00000000000
--- a/source/gameengine/SceneGraph/SG_DList.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#ifndef __SG_DLIST
-#define __SG_DLIST
-
-#include <stdlib.h>
-
-/**
- * Double circular linked list
- */
-class SG_DList
-{
-protected :
- SG_DList* m_flink;
- SG_DList* m_blink;
-
-public:
- template<typename T> class iterator
- {
- private:
- SG_DList& m_head;
- T* m_current;
- public:
- typedef iterator<T> _myT;
- iterator(SG_DList& head) : m_head(head), m_current(NULL) {}
- ~iterator() {}
-
- void begin()
- {
- m_current = (T*)m_head.Peek();
- }
- void back()
- {
- m_current = (T*)m_head.Back();
- }
- bool end()
- {
- return (m_current == (T*)m_head.Self());
- }
- bool add_back(T* item)
- {
- return m_current->AddBack(item);
- }
- T* operator*()
- {
- return m_current;
- }
- _myT& operator++()
- {
- // no check of NULL! make sure you don't try to increment beyond end
- m_current = (T*)m_current->Peek();
- return *this;
- }
- _myT& operator--()
- {
- // no check of NULL! make sure you don't try to increment beyond end
- m_current = (T*)m_current->Back();
- return *this;
- }
- };
-
- SG_DList()
- {
- m_flink = m_blink = this;
- }
- SG_DList(const SG_DList& other)
- {
- m_flink = m_blink = this;
- }
- virtual ~SG_DList()
- {
- Delink();
- }
-
- inline bool Empty() // Check for empty queue
- {
- return ( m_flink == this );
- }
- bool AddBack( SG_DList *item ) // Add to the back
- {
- if (!item->Empty())
- return false;
- item->m_blink = m_blink;
- item->m_flink = this;
- m_blink->m_flink = item;
- m_blink = item;
- return true;
- }
- bool AddFront( SG_DList *item ) // Add to the back
- {
- if (!item->Empty())
- return false;
- item->m_flink = m_flink;
- item->m_blink = this;
- m_flink->m_blink = item;
- m_flink = item;
- return true;
- }
- SG_DList *Remove() // Remove from the front
- {
- if (Empty())
- {
- return NULL;
- }
- SG_DList* item = m_flink;
- m_flink = item->m_flink;
- m_flink->m_blink = this;
- item->m_flink = item->m_blink = item;
- return item;
- }
- bool Delink() // Remove from the middle
- {
- if (Empty())
- return false;
- m_blink->m_flink = m_flink;
- m_flink->m_blink = m_blink;
- m_flink = m_blink = this;
- return true;
- }
- inline SG_DList *Peek() // Look at front without removing
- {
- return m_flink;
- }
- inline SG_DList *Back() // Look at front without removing
- {
- return m_blink;
- }
- inline SG_DList *Self()
- {
- return this;
- }
-};
-
-#endif //__SG_DLIST
-
diff --git a/source/gameengine/SceneGraph/SG_QList.h b/source/gameengine/SceneGraph/SG_QList.h
deleted file mode 100644
index d8afc33ea4f..00000000000
--- a/source/gameengine/SceneGraph/SG_QList.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#ifndef __SG_QLIST
-#define __SG_QLIST
-
-#include "SG_DList.h"
-
-/**
- * Double-Double circular linked list
- * For storing an object is two lists simultaneously
- */
-class SG_QList : public SG_DList
-{
-protected :
- SG_QList* m_fqlink;
- SG_QList* m_bqlink;
-
-public:
- template<typename T> class iterator
- {
- private:
- SG_QList& m_head;
- T* m_current;
- public:
- typedef iterator<T> _myT;
- iterator(SG_QList& head, SG_QList* current=NULL) : m_head(head) { m_current = (T*)current; }
- ~iterator() {}
-
- void begin()
- {
- m_current = (T*)m_head.QPeek();
- }
- void back()
- {
- m_current = (T*)m_head.QBack();
- }
- bool end()
- {
- return (m_current == (T*)m_head.Self());
- }
- bool add_back(T* item)
- {
- return m_current->QAddBack(item);
- }
- T* operator*()
- {
- return m_current;
- }
- _myT& operator++()
- {
- m_current = (T*)m_current->QPeek();
- return *this;
- }
- _myT& operator--()
- {
- // no check on NULL! make sure you don't try to increment beyond end
- m_current = (T*)m_current->QBack();
- return *this;
- }
- };
-
- SG_QList() : SG_DList()
- {
- m_fqlink = m_bqlink = this;
- }
- SG_QList(const SG_QList& other) : SG_DList()
- {
- m_fqlink = m_bqlink = this;
- }
- virtual ~SG_QList()
- {
- QDelink();
- }
-
- inline bool QEmpty() // Check for empty queue
- {
- return ( m_fqlink == this );
- }
- bool QAddBack( SG_QList *item ) // Add to the back
- {
- if (!item->QEmpty())
- return false;
- item->m_bqlink = m_bqlink;
- item->m_fqlink = this;
- m_bqlink->m_fqlink = item;
- m_bqlink = item;
- return true;
- }
- bool QAddFront( SG_QList *item ) // Add to the back
- {
- if (!item->Empty())
- return false;
- item->m_fqlink = m_fqlink;
- item->m_bqlink = this;
- m_fqlink->m_bqlink = item;
- m_fqlink = item;
- return true;
- }
- SG_QList *QRemove() // Remove from the front
- {
- if (QEmpty())
- {
- return NULL;
- }
- SG_QList* item = m_fqlink;
- m_fqlink = item->m_fqlink;
- m_fqlink->m_bqlink = this;
- item->m_fqlink = item->m_bqlink = item;
- return item;
- }
- bool QDelink() // Remove from the middle
- {
- if (QEmpty())
- return false;
- m_bqlink->m_fqlink = m_fqlink;
- m_fqlink->m_bqlink = m_bqlink;
- m_fqlink = m_bqlink = this;
- return true;
- }
- inline SG_QList *QPeek() // Look at front without removing
- {
- return m_fqlink;
- }
- inline SG_QList *QBack() // Look at front without removing
- {
- return m_bqlink;
- }
-};
-
-#endif //__SG_QLIST
-