Skip to content

Commit

Permalink
Some bugfixes and many improvements/additions
Browse files Browse the repository at this point in the history
- bugfix -> issue with refreshing thumbnails
- bugfix -> noupdating spritesheets while rendering
- sprites are now set as double sided
- armature modifier is set to preserve volume by default
- f key triggers a pie menu with many often used operator. increases workspeed alot
- New draw bone shape operator -> lets you quickly draw custom boneshapes for your bones
- much improved animation collections. Has now two modes. ACTION and NLA. If you like to make more complex NLA animtions this is now also possible.
- Wrap Animation Playback. Lets you loop playback animations with cursor keys. Once it reaches the end it jumps back to the beginning
- json export changes -> bone matrix calculations are working better now
- godot json import changes (reexport and reimport all files otherwise this won't work properly) Godot importer only supports uniform bone scaling
- other small improvements
  • Loading branch information
ndee85 committed Mar 30, 2016
1 parent 6bc059e commit 8f068b1
Show file tree
Hide file tree
Showing 12 changed files with 635 additions and 302 deletions.
81 changes: 51 additions & 30 deletions Blender/coa_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
class ExampleAddonPreferences(bpy.types.AddonPreferences):
bl_idname = __name__

show_donate_icon = bpy.props.BoolProperty(name="Show Donate Icon",default=True)
show_donate_icon = bpy.props.BoolProperty(name="Show Donate Icon",default=False)
sprite_import_export_scale = bpy.props.FloatProperty(name="Sprite import/export scale",default=0.01)
sprite_thumb_size = bpy.props.IntProperty(name="Sprite thumbnail size",default=48)
def draw(self, context):
Expand All @@ -70,7 +70,8 @@ def register_keymaps():
addon = bpy.context.window_manager.keyconfigs.addon
km = addon.keymaps.new(name = "3D View", space_type = "VIEW_3D")
# insert keymap items here
kmi = km.keymap_items.new("my_operator.select_frame_thumb", type = "F", value = "PRESS")
kmi = km.keymap_items.new("wm.call_menu_pie", type = "F", value = "PRESS")
kmi.properties.name = "view3d.coa_pie_menu"
addon_keymaps.append(km)

def unregister_keymaps():
Expand Down Expand Up @@ -136,37 +137,50 @@ def unregister():
def update_sprites(dummy):
bpy.context.scene.coa_ticker += 1
update_scene = False
try:
context = bpy.context

for obj in bpy.context.visible_objects:
if "sprite" in obj and obj.animation_data != None and obj.animation_data.action != None and obj.type == "MESH":
if obj.coa_sprite_frame != obj.coa_sprite_frame_last:
update_uv(bpy.context,obj)
obj.coa_sprite_frame_last = obj.coa_sprite_frame
if obj.coa_alpha != obj.coa_alpha_last:
set_alpha(obj,bpy.context,obj.coa_alpha)
obj.coa_alpha_last = obj.coa_alpha
update_scene = True
if obj.coa_z_value != obj.coa_z_value_last:
set_z_value(context,obj,obj.coa_z_value)
obj.coa_z_value_last = obj.coa_z_value
if obj.coa_modulate_color != obj.coa_modulate_color_last:
set_modulate_color(obj,context,obj.coa_modulate_color)
obj.coa_modulate_color_last = obj.coa_modulate_color

except:
pass
if bpy.context.scene.coa_ticker%3 == 0 and update_scene:
bpy.context.scene.update()

context = bpy.context
objects = []

if hasattr(context,"visible_objects"):
objects = context.visible_objects
else:
objects = bpy.data.objects

sprite_object = get_sprite_object(context.active_object)
if sprite_object != None and sprite_object.coa_animation_loop:
if context.scene.frame_current > sprite_object.coa_anim_collections[sprite_object.coa_anim_collections_index].frame_end:
context.scene.frame_current = 0

for obj in objects:
if "coa_sprite" in obj and obj.animation_data != None and obj.animation_data.action != None and obj.type == "MESH":
if obj.coa_sprite_frame != obj.coa_sprite_frame_last:
update_uv(bpy.context,obj)
obj.coa_sprite_frame_last = int(obj.coa_sprite_frame)
if obj.coa_alpha != obj.coa_alpha_last:
set_alpha(obj,bpy.context,obj.coa_alpha)
obj.coa_alpha_last = obj.coa_alpha
update_scene = True
if obj.coa_z_value != obj.coa_z_value_last:
set_z_value(context,obj,obj.coa_z_value)
obj.coa_z_value_last = obj.coa_z_value
if obj.coa_modulate_color != obj.coa_modulate_color_last:
set_modulate_color(obj,context,obj.coa_modulate_color)
obj.coa_modulate_color_last = obj.coa_modulate_color

if bpy.context.scene.coa_ticker%3 == 0 and update_scene:
bpy.context.scene.update()



@persistent
def update_thumbs(dummy):
obj = bpy.context.active_object
if obj != None and not obj.coa_sprite_updated:
for thumb in preview_collections["coa_thumbs"]:
preview_collections["coa_thumbs"][thumb].reload()
obj.coa_sprite_updated = True
if hasattr(bpy.context,"active_object"):

obj = bpy.context.active_object
if obj != None and not obj.coa_sprite_updated and obj.name in preview_collections["coa_thumbs"]:
for thumb in preview_collections["coa_thumbs"]:
preview_collections["coa_thumbs"][thumb].reload()
obj.coa_sprite_updated = True


### start modal operator
Expand All @@ -184,6 +198,13 @@ def scene_update_callback(scene):
def coa_startup(dummy):
print("startup coa modal operator")
bpy.app.handlers.scene_update_pre.append(scene_update_callback)
for obj in bpy.data.objects:
if obj.type == "MESH":
if "sprite" in obj:
obj["coa_sprite"] = True
del obj["sprite"]
obj.coa_sprite_updated = False
obj.coa_tiles_changed = True



Expand Down
75 changes: 54 additions & 21 deletions Blender/coa_tools/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,31 @@
import json
from bpy.app.handlers import persistent


def get_uv_from_vert(uv_layer, v):
for l in v.link_loops:
if v.select:
uv_data = l[uv_layer]
return uv_data

def update_uv_unwrap(context):
obj = context.active_object
me = obj.data
bm = bmesh.from_edit_mesh(me)

### pin uv boundary vertex
uv_layer = bm.loops.layers.uv.active
for vert in bm.verts:

uv_vert = get_uv_from_vert(uv_layer, vert)
if uv_vert != None:
print(vert.co.xz,"----",uv_vert.uv)


bmesh.update_edit_mesh(me)



def clamp(n, minn, maxn):
return max(min(maxn, n), minn)

Expand All @@ -41,6 +66,24 @@ def b_version_bigger_than(version):
else:
return False

def check_region(context,event):
in_view_3d = False
if context.area != None:
if context.area.type == "VIEW_3D":
t_panel = context.area.regions[1]
n_panel = context.area.regions[3]

view_3d_region_x = Vector((context.area.x + t_panel.width, context.area.x + context.area.width - n_panel.width))
view_3d_region_y = Vector((context.region.y, context.region.y+context.region.height))

if event.mouse_x > view_3d_region_x[0] and event.mouse_x < view_3d_region_x[1] and event.mouse_y > view_3d_region_y[0] and event.mouse_y < view_3d_region_y[1]:
in_view_3d = True
else:
in_view_3d = False
else:
in_view_3d = False
return in_view_3d

def get_local_dimension(obj):
x0 = 10000000000*10000000000
x1 = -10000000000*10000000000
Expand Down Expand Up @@ -102,7 +145,7 @@ def create_action(context,item=None):
if obj.animation_data == None:
obj.animation_data_create()
obj.animation_data.action = action
context.scene.update()
context.scene.update()

def set_action(context,item=None):
sprite_object = get_sprite_object(context.active_object)
Expand All @@ -112,7 +155,6 @@ def set_action(context,item=None):
for child in get_children(context,sprite_object,ob_list=[]):
if child.animation_data != None:
child.animation_data.action = None
child.animation_data_clear()

if child.type == "ARMATURE" and item.name == "Restpose":
for bone in child.pose.bones:
Expand All @@ -124,7 +166,7 @@ def set_action(context,item=None):
child.coa_sprite_frame = 0
child.coa_alpha = 1.0
child.coa_modulate_color = (1.0,1.0,1.0)
else:
elif not (child.type == "MESH" and item.name == "Restpose") and context.scene.coa_nla_mode == "ACTION":
action_name = item.name + "_" + child.name

action = None
Expand Down Expand Up @@ -154,6 +196,7 @@ def set_local_view(local):
else:
if area.spaces.active.local_view != None:
bpy.ops.view3d.localview()


def actions_callback(self,context):
actions = []
Expand Down Expand Up @@ -313,9 +356,9 @@ def get_children(context,obj,ob_list=[]):


def update_uv(context,obj):
if "sprite" in obj and len(obj.data.vertices) == 4:
if "coa_sprite" in obj and len(obj.data.vertices) == 4:
mode_prev = obj.mode
if obj == context.active_object and obj.type == "MESH":
if hasattr(context,"active_object") and obj == context.active_object and obj.type == "MESH":
bpy.ops.object.mode_set(mode="OBJECT")
coord1 = obj.data.uv_layers[obj.data.uv_layers.active.name].data[0]
coord2 = obj.data.uv_layers[obj.data.uv_layers.active.name].data[1]
Expand All @@ -337,22 +380,13 @@ def update_uv(context,obj):
coord3.uv = Vector((1.0 / anim_data.coa_tiles_x,1.0 / anim_data.coa_tiles_y)) + offset + frame
coord4.uv = Vector((0.0 / anim_data.coa_tiles_x,1.0 / anim_data.coa_tiles_y)) + offset + frame

if obj == context.active_object and obj.type == "MESH":

if hasattr(context,"active_object") and obj == context.active_object and obj.type == "MESH":
bpy.ops.object.mode_set(mode=mode_prev)

def update_verts(context,obj):
if "sprite" in obj and len(obj.data.vertices) == 4:
def update_verts(context,obj):
if "coa_sprite" in obj and len(obj.data.vertices) == 4:
mode_prev = obj.mode
armature = get_armature(get_sprite_object(obj))
pose_position = ""
if armature != None:
pose_position = armature.data.pose_position
armature.data.pose_position = "REST"
context.scene.objects.active = armature
mode = armature.mode
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.object.mode_set(mode=mode)
context.scene.objects.active = obj

obj.coa_dimensions_old = Vector(obj.dimensions)
sprite_sheet_width = obj.data.uv_textures[0].data[0].image.size[0]
Expand All @@ -368,8 +402,6 @@ def update_verts(context,obj):
vert.co[0] = vert.co[0] / obj.coa_dimensions_old[0] * sprite_sheet_width / anim_data.coa_tiles_x * scale_x * obj.matrix_world.to_scale()[0]
vert.co[2] = vert.co[2] / obj.coa_dimensions_old[2] * sprite_sheet_height / anim_data.coa_tiles_y * scale_y * obj.matrix_world.to_scale()[2]

if armature != None:
armature.data.pose_position = pose_position
bpy.ops.object.mode_set(mode=mode_prev)

def set_z_value(context,obj,z):
Expand Down Expand Up @@ -419,9 +451,10 @@ def display_children(self, context, obj):


if sprite_object.coa_show_children:
for child in children:
for i,child in enumerate(children):
if (obj.coa_favorite and child.coa_favorite) or not obj.coa_favorite:
if obj.coa_filter_names in child.name:

row = col.row(align=True)
row.separator()
row.separator()
Expand Down
118 changes: 117 additions & 1 deletion Blender/coa_tools/operators/animation_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,120 @@ def execute(self, context):
self.remove_actions_collection(context)

return {"FINISHED"}


class CreateNlaTrack(bpy.types.Operator):
bl_idname = "coa_operator.create_nla_track"
bl_label = "Create NLA Track"
bl_description = "Generate NLA Strips."
bl_options = {"REGISTER","UNDO"}


start = IntProperty(default=0)
repeat = IntProperty(default=1)
scale = FloatProperty(default=1.0)
insert_at_cursor = BoolProperty(default=True)
anim_collection_name = StringProperty()
auto_blend = BoolProperty(default=True)

def check(self,context):
return True

@classmethod
def poll(cls, context):
return True

def draw(self,context):
layout = self.layout
row = layout.row()
row.prop(self,"insert_at_cursor",text="Insert Strip at Cursor Location")
row = layout.row()
row.prop(self,"auto_blend",text="Auto Blending")
row = layout.row()
if self.insert_at_cursor:
row.active = False
row.enabled = False
row.prop(self,"start",text="Insert at Frame")
row = layout.row()
row.prop(self,"repeat",text="Repeat Strip")
row = layout.row()
row.prop(self,"scale",text="Scale Strip")


def invoke(self,context,event):
wm = context.window_manager
self.start = 0
self.repeat = 1
self.scale = 1.0
#self.insert_at_cursor = True
return wm.invoke_props_dialog(self)

def get_empty_track(self,anim_data,strip_range):
if len(anim_data.nla_tracks) == 0:
return anim_data.nla_tracks.new()

strip_space = range(strip_range[0],strip_range[1]+1)
for i,track in enumerate(anim_data.nla_tracks):
track = anim_data.nla_tracks[i]

if len(track.strips) == 0:
return track

intersecting_strip_found = False
for strip in track.strips:
if strip.frame_start in strip_space or strip.frame_end in strip_space:
intersecting_strip_found = True
if not intersecting_strip_found:
return track

return anim_data.nla_tracks.new()

def execute(self, context):
obj = bpy.context.active_object
sprite_object = get_sprite_object(obj)
children = get_children(context,sprite_object,ob_list=[])

context.scene.coa_nla_mode = "NLA"

if self.anim_collection_name == "":
anim_collection = sprite_object.coa_anim_collections[sprite_object.coa_anim_collections_index]
else:
anim_collection = sprite_object.coa_anim_collections[self.anim_collection_name]

if self.insert_at_cursor:
self.start = context.scene.frame_current

for child in children:
if child.animation_data != None:
for track in child.animation_data.nla_tracks:
for strip in track.strips:
strip.select = False

action_name = anim_collection.name + "_" + child.name
if action_name in bpy.data.actions:
action_start = 0
action_end = anim_collection.frame_end
strip_start = self.start
strip_end = self.start + anim_collection.frame_end


action = bpy.data.actions[action_name]

if child.animation_data != None:
child.animation_data_create()
anim_data = child.animation_data

nla_track = self.get_empty_track(anim_data,[strip_start,strip_end])

strip = nla_track.strips.new(action_name,self.start,action)
strip.action_frame_start = action_start
strip.action_frame_end = action_end

strip.frame_start = strip_start
strip.frame_end = strip_end
strip.repeat = self.repeat
strip.use_auto_blend = self.auto_blend
strip.scale = self.scale


return {"FINISHED"}

Loading

0 comments on commit 8f068b1

Please sign in to comment.