armory/blender/addon/armory.py
2017-11-22 22:13:55 +01:00

252 lines
8.6 KiB
Python
Executable file

# Armory 3D Engine
# https://github.com/armory3d/armory
bl_info = {
"name": "Armory",
"category": "Render",
"location": "Properties -> Render -> Armory Player",
"description": "3D game engine for Blender",
"author": "Armory3D.org",
"version": (11, 4, 0),
"blender": (2, 79, 0),
"wiki_url": "http://armory3d.org/manual",
"tracker_url": "https://github.com/armory3d/armory/issues"
}
import os
import sys
import stat
import shutil
import webbrowser
import subprocess
import bpy
from bpy.types import Operator, AddonPreferences
from bpy.props import *
from bpy.app.handlers import persistent
with_krom = False
class ArmoryAddonPreferences(AddonPreferences):
bl_idname = __name__
def sdk_path_update(self, context):
if self.skip_update:
return
self.skip_update = True
self.sdk_path = bpy.path.reduce_dirs([bpy.path.abspath(self.sdk_path)])[0] + '/'
def ffmpeg_path_update(self, context):
if self.skip_update:
return
self.skip_update = True
self.ffmpeg_path = bpy.path.reduce_dirs([bpy.path.abspath(self.ffmpeg_path)])[0]
def renderdoc_path_update(self, context):
if self.skip_update:
return
self.skip_update = True
self.renderdoc_path = bpy.path.reduce_dirs([bpy.path.abspath(self.renderdoc_path)])[0]
sdk_bundled = BoolProperty(name="Bundled SDK", default=True)
sdk_path = StringProperty(name="SDK Path", subtype="FILE_PATH", update=sdk_path_update, default="")
show_advanced = BoolProperty(name="Show Advanced", default=False)
renderdoc_path = StringProperty(name="RenderDoc Path", subtype="FILE_PATH", update=renderdoc_path_update, default="")
ffmpeg_path = StringProperty(name="FFMPEG Path", subtype="FILE_PATH", update=ffmpeg_path_update, default="")
save_on_build = BoolProperty(name="Save on Build", default=True)
viewport_controls = EnumProperty(
items=[('qwerty', 'qwerty', 'qwerty'),
('azerty', 'azerty', 'azerty')],
name="Viewport Controls", default='qwerty', description='Viewport camera mode controls')
skip_update = BoolProperty(name="", default=False)
def draw(self, context):
global with_krom
self.skip_update = False
layout = self.layout
layout.label(text="Welcome to Armory! Click 'Save User Settings' at the bottom to keep Armory enabled.")
if with_krom:
layout.prop(self, "sdk_bundled")
if not self.sdk_bundled:
layout.prop(self, "sdk_path")
else:
layout.prop(self, "sdk_path")
layout.prop(self, "show_advanced")
if self.show_advanced:
layout.prop(self, "renderdoc_path")
layout.prop(self, "ffmpeg_path")
layout.prop(self, "viewport_controls")
layout.prop(self, "save_on_build")
layout.separator()
layout.label("Armory Updater")
layout.label("Note: Development version may run unstable!")
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.operator("arm_addon.install_git", icon="URL")
row.operator("arm_addon.update", icon="FILE_REFRESH")
row.operator("arm_addon.restore")
layout.label("Please restart Blender after successful SDK update.")
def get_os():
import platform
s = platform.system()
if s == 'Windows':
return 'win'
elif s == 'Darwin':
return 'mac'
else:
return 'linux'
def get_sdk_path(context):
global with_krom
user_preferences = context.user_preferences
addon_prefs = user_preferences.addons["armory"].preferences
if with_krom and addon_prefs.sdk_bundled:
if get_os() == 'mac':
# SDK on MacOS is located in .app folder due to security
p = bpy.app.binary_path
if p.endswith('Contents/MacOS/blender'):
return p[:-len('Contents/MacOS/blender')] + '/armsdk/'
else:
return p[:-len('Contents/MacOS/./blender')] + '/armsdk/'
elif get_os() == 'linux':
# /blender
return bpy.app.binary_path.rsplit('/', 1)[0] + '/armsdk/'
else:
# /blender.exe
return bpy.app.binary_path.replace('\\', '/').rsplit('/', 1)[0] + '/armsdk/'
else:
return addon_prefs.sdk_path
def remove_readonly(func, path, excinfo):
os.chmod(path, stat.S_IWRITE)
func(path)
def update_repo(p, n, gitn = ''):
if gitn == '':
gitn = n
if not os.path.exists(p + '/' + n + '_backup'):
os.rename(p + '/' + n, p + '/' + n + '_backup')
if os.path.exists(p + '/' + n):
shutil.rmtree(p + '/' + n, onerror=remove_readonly)
subprocess.Popen(['git', 'clone', 'https://github.com/armory3d/' + gitn, p + '/' + n, '--depth=1'])
def restore_repo(p, n):
if os.path.exists(p + '/' + n + '_backup'):
if os.path.exists(p + '/' + n):
shutil.rmtree(p + '/' + n, onerror=remove_readonly)
os.rename(p + '/' + n + '_backup', p + '/' + n)
class ArmAddonStartButton(bpy.types.Operator):
'''Start Armory integration'''
bl_idname = "arm_addon.start"
bl_label = "Start"
running = False
play_in_viewport = False
def execute(self, context):
sdk_path = get_sdk_path(context)
if sdk_path == "":
self.report({"ERROR"}, "Configure SDK path first")
return {"CANCELLED"}
scripts_path = sdk_path + "/armory/blender/"
sys.path.append(scripts_path)
import start
start.register()
ArmAddonStartButton.running = True
if not hasattr(bpy.app.handlers, 'scene_update_post'): # 2.8
bpy.types.VIEW3D_HT_header.remove(draw_view3d_header)
return {"FINISHED"}
class ArmAddonStopButton(bpy.types.Operator):
'''Stop Armory integration'''
bl_idname = "arm_addon.stop"
bl_label = "Stop"
def execute(self, context):
import start
start.unregister()
ArmAddonStartButton.running = False
return {"FINISHED"}
class ArmAddonUpdateButton(bpy.types.Operator):
'''Update Armory SDK'''
bl_idname = "arm_addon.update"
bl_label = "Update SDK"
bl_description = "Update to the latest development version"
def execute(self, context):
p = get_sdk_path(context)
if p == "":
self.report({"ERROR"}, "Configure SDK path first")
return {"CANCELLED"}
self.report({'INFO'}, 'Updating, check console for details.')
print('Armory: Cloning [armory, iron, haxebullet, haxerecast, zui] repositories')
os.chdir(p)
update_repo(p, 'armory')
update_repo(p, 'iron')
update_repo(p, 'lib/haxebullet', 'haxebullet')
update_repo(p, 'lib/haxerecast', 'haxerecast')
update_repo(p, 'lib/zui', 'zui')
return {"FINISHED"}
class ArmAddonRestoreButton(bpy.types.Operator):
'''Update Armory SDK'''
bl_idname = "arm_addon.restore"
bl_label = "Restore SDK"
bl_description = "Restore stable version"
def execute(self, context):
p = get_sdk_path(context)
if p == "":
self.report({"ERROR"}, "Configure SDK path first")
return {"CANCELLED"}
os.chdir(p)
restore_repo(p, 'armory')
restore_repo(p, 'iron')
restore_repo(p, 'lib/haxebullet')
restore_repo(p, 'lib/haxerecast')
restore_repo(p, 'lib/zui')
self.report({'INFO'}, 'Restored stable version.')
return {"FINISHED"}
class ArmAddonInstallGitButton(bpy.types.Operator):
'''Install Git'''
bl_idname = "arm_addon.install_git"
bl_label = "Install Git"
bl_description = "Git is required for Armory Updater to work"
def execute(self, context):
webbrowser.open('https://git-scm.com')
return {"FINISHED"}
@persistent
def on_scene_update_post(scene):
if hasattr(bpy.app.handlers, 'scene_update_post'):
bpy.app.handlers.scene_update_post.remove(on_scene_update_post)
bpy.ops.arm_addon.start()
def draw_view3d_header(self, context):
layout = self.layout
layout.operator("arm_addon.start")
def register():
global with_krom
import importlib.util
if importlib.util.find_spec('barmory') != None:
with_krom = True
bpy.utils.register_module(__name__)
if hasattr(bpy.app.handlers, 'scene_update_post'):
bpy.app.handlers.scene_update_post.append(on_scene_update_post)
else: # 2.8
bpy.types.VIEW3D_HT_header.append(draw_view3d_header)
def unregister():
bpy.ops.arm_addon.stop()
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()