2017-11-22 22:13:55 +01:00
|
|
|
# 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",
|
2018-02-16 18:09:03 +01:00
|
|
|
"version": (11, 6, 0),
|
2017-11-22 22:13:55 +01:00
|
|
|
"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)
|
2018-02-16 18:09:03 +01:00
|
|
|
legacy_shaders = BoolProperty(name="Legacy Shaders", default=False)
|
2017-11-22 22:13:55 +01:00
|
|
|
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")
|
2018-02-16 18:09:03 +01:00
|
|
|
layout.prop(self, "legacy_shaders")
|
2017-11-22 22:13:55 +01:00
|
|
|
|
|
|
|
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"}
|
2017-12-05 23:13:37 +01:00
|
|
|
self.report({'INFO'}, 'Updating, check console for details. Please restart Blender after successful SDK update.')
|
2017-12-06 12:36:39 +01:00
|
|
|
print('Armory (add-on v' + str(bl_info['version']) + '): Cloning [armory, iron, haxebullet, haxerecast, zui] repositories')
|
2017-11-22 22:13:55 +01:00
|
|
|
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()
|