A few addons related cleanup after BGE removal
This commit is contained in:
parent
b4a92f1396
commit
e6a5a2a679
|
@ -1,576 +0,0 @@
|
|||
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
import os
|
||||
import tempfile
|
||||
import shutil
|
||||
import tarfile
|
||||
import time
|
||||
import stat
|
||||
|
||||
|
||||
bl_info = {
|
||||
"name": "Game Engine Publishing",
|
||||
"author": "Mitchell Stokes (Moguri), Oren Titane (Genome36)",
|
||||
"version": (0, 1, 0),
|
||||
"blender": (2, 75, 0),
|
||||
"location": "Render Properties > Publishing Info",
|
||||
"description": "Publish .blend file as game engine runtime, manage versions and platforms",
|
||||
"warning": "",
|
||||
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Game_Engine/Publishing",
|
||||
"category": "Game Engine",
|
||||
}
|
||||
|
||||
|
||||
def WriteRuntime(player_path, output_path, asset_paths, copy_python, overwrite_lib, copy_dlls, make_archive, report=print):
|
||||
import struct
|
||||
|
||||
player_path = bpy.path.abspath(player_path)
|
||||
ext = os.path.splitext(player_path)[-1].lower()
|
||||
output_path = bpy.path.abspath(output_path)
|
||||
output_dir = os.path.dirname(output_path)
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
python_dir = os.path.join(os.path.dirname(player_path),
|
||||
bpy.app.version_string.split()[0],
|
||||
"python",
|
||||
"lib")
|
||||
|
||||
# Check the paths
|
||||
if not os.path.isfile(player_path) and not(os.path.exists(player_path) and player_path.endswith('.app')):
|
||||
report({'ERROR'}, "The player could not be found! Runtime not saved")
|
||||
return
|
||||
|
||||
# Check if we're bundling a .app
|
||||
if player_path.lower().endswith('.app'):
|
||||
# Python doesn't need to be copied for OS X since it's already inside blenderplayer.app
|
||||
copy_python = False
|
||||
|
||||
output_path = bpy.path.ensure_ext(output_path, '.app')
|
||||
|
||||
if os.path.exists(output_path):
|
||||
shutil.rmtree(output_path)
|
||||
|
||||
shutil.copytree(player_path, output_path)
|
||||
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(output_path, 'Contents', 'Resources', 'game.blend'),
|
||||
relative_remap=False,
|
||||
compress=False,
|
||||
copy=True,
|
||||
)
|
||||
else:
|
||||
# Enforce "exe" extension on Windows
|
||||
if player_path.lower().endswith('.exe'):
|
||||
output_path = bpy.path.ensure_ext(output_path, '.exe')
|
||||
|
||||
# Get the player's binary and the offset for the blend
|
||||
with open(player_path, "rb") as file:
|
||||
player_d = file.read()
|
||||
offset = file.tell()
|
||||
|
||||
# Create a tmp blend file (Blenderplayer doesn't like compressed blends)
|
||||
tempdir = tempfile.mkdtemp()
|
||||
blend_path = os.path.join(tempdir, bpy.path.clean_name(output_path))
|
||||
bpy.ops.wm.save_as_mainfile(filepath=blend_path,
|
||||
relative_remap=False,
|
||||
compress=False,
|
||||
copy=True,
|
||||
)
|
||||
|
||||
# Get the blend data
|
||||
with open(blend_path, "rb") as blend_file:
|
||||
blend_d = blend_file.read()
|
||||
|
||||
# Get rid of the tmp blend, we're done with it
|
||||
os.remove(blend_path)
|
||||
os.rmdir(tempdir)
|
||||
|
||||
# Create a new file for the bundled runtime
|
||||
with open(output_path, "wb") as output:
|
||||
# Write the player and blend data to the new runtime
|
||||
print("Writing runtime...", end=" ", flush=True)
|
||||
output.write(player_d)
|
||||
output.write(blend_d)
|
||||
|
||||
# Store the offset (an int is 4 bytes, so we split it up into 4 bytes and save it)
|
||||
output.write(struct.pack('BBBB', (offset >> 24) & 0xFF,
|
||||
(offset >> 16) & 0xFF,
|
||||
(offset >> 8) & 0xFF,
|
||||
(offset >> 0) & 0xFF))
|
||||
|
||||
# Stuff for the runtime
|
||||
output.write(b'BRUNTIME')
|
||||
|
||||
print("done", flush=True)
|
||||
|
||||
# Make sure the runtime is executable
|
||||
os.chmod(output_path, 0o755)
|
||||
|
||||
# Copy bundled Python
|
||||
blender_dir = os.path.dirname(player_path)
|
||||
|
||||
if copy_python:
|
||||
print("Copying Python files...", end=" ", flush=True)
|
||||
py_folder = os.path.join(bpy.app.version_string.split()[0], "python", "lib")
|
||||
dst = os.path.join(output_dir, py_folder)
|
||||
src = python_dir
|
||||
|
||||
if os.path.exists(dst) and overwrite_lib:
|
||||
shutil.rmtree(dst)
|
||||
|
||||
if not os.path.exists(dst):
|
||||
shutil.copytree(src, dst, ignore=lambda dir, contents: [i for i in contents if i == '__pycache__'])
|
||||
print("done", flush=True)
|
||||
else:
|
||||
print("used existing Python folder", flush=True)
|
||||
|
||||
# And DLLs if we're doing a Windows runtime)
|
||||
if copy_dlls and ext == ".exe":
|
||||
print("Copying DLLs...", end=" ", flush=True)
|
||||
for file in [i for i in os.listdir(blender_dir) if i.lower().endswith('.dll')]:
|
||||
src = os.path.join(blender_dir, file)
|
||||
dst = os.path.join(output_dir, file)
|
||||
shutil.copy2(src, dst)
|
||||
|
||||
print("done", flush=True)
|
||||
|
||||
# Copy assets
|
||||
for ap in asset_paths:
|
||||
src = bpy.path.abspath(ap.name)
|
||||
dst = os.path.join(output_dir, ap.name[2:] if ap.name.startswith('//') else ap.name)
|
||||
|
||||
if os.path.exists(src):
|
||||
if os.path.isdir(src):
|
||||
if ap.overwrite and os.path.exists(dst):
|
||||
shutil.rmtree(dst)
|
||||
elif not os.path.exists(dst):
|
||||
shutil.copytree(src, dst)
|
||||
else:
|
||||
if ap.overwrite or not os.path.exists(dst):
|
||||
shutil.copy2(src, dst)
|
||||
else:
|
||||
report({'ERROR'}, "Could not find asset path: '%s'" % src)
|
||||
|
||||
# Make archive
|
||||
if make_archive:
|
||||
print("Making archive...", end=" ", flush=True)
|
||||
|
||||
arctype = ''
|
||||
if player_path.lower().endswith('.exe'):
|
||||
arctype = 'zip'
|
||||
elif player_path.lower().endswith('.app'):
|
||||
arctype = 'zip'
|
||||
else: # Linux
|
||||
arctype = 'gztar'
|
||||
|
||||
basedir = os.path.normpath(os.path.join(os.path.dirname(output_path), '..'))
|
||||
afilename = os.path.join(basedir, os.path.basename(output_dir))
|
||||
|
||||
if arctype == 'gztar':
|
||||
# Create the tarball ourselves instead of using shutil.make_archive
|
||||
# so we can handle permission bits.
|
||||
|
||||
# The runtimename needs to use forward slashes as a path separator
|
||||
# since this is what tarinfo.name is using.
|
||||
runtimename = os.path.relpath(output_path, basedir).replace('\\', '/')
|
||||
|
||||
def _set_ex_perm(tarinfo):
|
||||
if tarinfo.name == runtimename:
|
||||
tarinfo.mode = 0o755
|
||||
return tarinfo
|
||||
|
||||
with tarfile.open(afilename + '.tar.gz', 'w:gz') as tf:
|
||||
tf.add(output_dir, os.path.relpath(output_dir, basedir), filter=_set_ex_perm)
|
||||
elif arctype == 'zip':
|
||||
shutil.make_archive(afilename, 'zip', output_dir)
|
||||
else:
|
||||
report({'ERROR'}, "Unknown archive type %s for runtime %s\n" % (arctype, player_path))
|
||||
|
||||
print("done", flush=True)
|
||||
|
||||
|
||||
class PublishAllPlatforms(bpy.types.Operator):
|
||||
bl_idname = "wm.publish_platforms"
|
||||
bl_label = "Exports a runtime for each listed platform"
|
||||
|
||||
def execute(self, context):
|
||||
ps = context.scene.ge_publish_settings
|
||||
|
||||
if ps.publish_default_platform:
|
||||
print("Publishing default platform")
|
||||
blender_bin_path = bpy.app.binary_path
|
||||
blender_bin_dir = os.path.dirname(blender_bin_path)
|
||||
ext = os.path.splitext(blender_bin_path)[-1].lower()
|
||||
WriteRuntime(os.path.join(blender_bin_dir, 'blenderplayer' + ext),
|
||||
os.path.join(ps.output_path, 'default', ps.runtime_name),
|
||||
ps.asset_paths,
|
||||
True,
|
||||
True,
|
||||
True,
|
||||
ps.make_archive,
|
||||
self.report
|
||||
)
|
||||
else:
|
||||
print("Skipping default platform")
|
||||
|
||||
for platform in ps.platforms:
|
||||
if platform.publish:
|
||||
print("Publishing", platform.name)
|
||||
WriteRuntime(platform.player_path,
|
||||
os.path.join(ps.output_path, platform.name, ps.runtime_name),
|
||||
ps.asset_paths,
|
||||
True,
|
||||
True,
|
||||
True,
|
||||
ps.make_archive,
|
||||
self.report
|
||||
)
|
||||
else:
|
||||
print("Skipping", platform.name)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class RENDER_UL_assets(bpy.types.UIList):
|
||||
bl_label = "Asset Paths Listing"
|
||||
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
layout.prop(item, "name", text="", emboss=False)
|
||||
|
||||
|
||||
class RENDER_UL_platforms(bpy.types.UIList):
|
||||
bl_label = "Platforms Listing"
|
||||
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
row = layout.row()
|
||||
row.label(item.name)
|
||||
row.prop(item, "publish", text="")
|
||||
|
||||
|
||||
class RENDER_PT_publish(bpy.types.Panel):
|
||||
bl_label = "Publishing Info"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "render"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
scene = context.scene
|
||||
return scene and (scene.render.engine == "BLENDER_GAME")
|
||||
|
||||
def draw(self, context):
|
||||
ps = context.scene.ge_publish_settings
|
||||
layout = self.layout
|
||||
|
||||
# config
|
||||
layout.prop(ps, 'output_path')
|
||||
layout.prop(ps, 'runtime_name')
|
||||
layout.prop(ps, 'lib_path')
|
||||
layout.prop(ps, 'make_archive')
|
||||
|
||||
layout.separator()
|
||||
|
||||
# assets list
|
||||
layout.label("Asset Paths")
|
||||
|
||||
# UI_UL_list
|
||||
row = layout.row()
|
||||
row.template_list("RENDER_UL_assets", "assets_list", ps, 'asset_paths', ps, 'asset_paths_active')
|
||||
|
||||
# operators
|
||||
col = row.column(align=True)
|
||||
col.operator(PublishAddAssetPath.bl_idname, icon='ZOOMIN', text="")
|
||||
col.operator(PublishRemoveAssetPath.bl_idname, icon='ZOOMOUT', text="")
|
||||
|
||||
# indexing
|
||||
if len(ps.asset_paths) > ps.asset_paths_active >= 0:
|
||||
ap = ps.asset_paths[ps.asset_paths_active]
|
||||
row = layout.row()
|
||||
row.prop(ap, 'overwrite')
|
||||
|
||||
layout.separator()
|
||||
|
||||
# publishing list
|
||||
row = layout.row(align=True)
|
||||
row.label("Platforms")
|
||||
row.prop(ps, 'publish_default_platform')
|
||||
|
||||
# UI_UL_list
|
||||
row = layout.row()
|
||||
row.template_list("RENDER_UL_platforms", "platforms_list", ps, 'platforms', ps, 'platforms_active')
|
||||
|
||||
# operators
|
||||
col = row.column(align=True)
|
||||
col.operator(PublishAddPlatform.bl_idname, icon='ZOOMIN', text="")
|
||||
col.operator(PublishRemovePlatform.bl_idname, icon='ZOOMOUT', text="")
|
||||
col.menu("PUBLISH_MT_platform_specials", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
# indexing
|
||||
if len(ps.platforms) > ps.platforms_active >= 0:
|
||||
platform = ps.platforms[ps.platforms_active]
|
||||
layout.prop(platform, 'name')
|
||||
layout.prop(platform, 'player_path')
|
||||
|
||||
layout.operator(PublishAllPlatforms.bl_idname, 'Publish Platforms')
|
||||
|
||||
|
||||
class PublishAutoPlatforms(bpy.types.Operator):
|
||||
bl_idname = "scene.publish_auto_platforms"
|
||||
bl_label = "Auto Add Platforms"
|
||||
|
||||
def execute(self, context):
|
||||
ps = context.scene.ge_publish_settings
|
||||
|
||||
# verify lib folder
|
||||
lib_path = bpy.path.abspath(ps.lib_path)
|
||||
if not os.path.exists(lib_path):
|
||||
self.report({'ERROR'}, "Could not add platforms, lib folder (%s) does not exist" % lib_path)
|
||||
return {'CANCELLED'}
|
||||
|
||||
for lib in [i for i in os.listdir(lib_path) if os.path.isdir(os.path.join(lib_path, i))]:
|
||||
print("Found folder:", lib)
|
||||
player_found = False
|
||||
for root, dirs, files in os.walk(os.path.join(lib_path, lib)):
|
||||
if "__MACOSX" in root:
|
||||
continue
|
||||
|
||||
for f in dirs + files:
|
||||
if f.startswith("blenderplayer.app") or f.startswith("blenderplayer"):
|
||||
a = ps.platforms.add()
|
||||
if lib.startswith('blender-'):
|
||||
# Clean up names for packages from blender.org
|
||||
# example: blender-2.71-RC2-OSX_10.6-x86_64.zip => OSX_10.6-x86_64.zip
|
||||
# We're pretty consistent on naming, so this should hold up.
|
||||
a.name = '-'.join(lib.split('-')[3 if 'rc' in lib.lower() else 2:])
|
||||
else:
|
||||
a.name = lib
|
||||
a.player_path = bpy.path.relpath(os.path.join(root, f))
|
||||
player_found = True
|
||||
break
|
||||
|
||||
if player_found:
|
||||
break
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
# TODO This operator takes a long time to run, which is bad for UX. Could this instead be done as some sort of
|
||||
# modal dialog? This could also allow users to select which platforms to download and give a better progress
|
||||
# indicator.
|
||||
class PublishDownloadPlatforms(bpy.types.Operator):
|
||||
bl_idname = "scene.publish_download_platforms"
|
||||
bl_label = "Download Platforms"
|
||||
|
||||
def execute(self, context):
|
||||
import html.parser
|
||||
import urllib.request
|
||||
|
||||
remote_platforms = []
|
||||
|
||||
ps = context.scene.ge_publish_settings
|
||||
|
||||
# create lib folder if not already available
|
||||
lib_path = bpy.path.abspath(ps.lib_path)
|
||||
if not os.path.exists(lib_path):
|
||||
os.makedirs(lib_path)
|
||||
|
||||
print("Retrieving list of platforms from blender.org...", end=" ", flush=True)
|
||||
|
||||
class AnchorParser(html.parser.HTMLParser):
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if tag == 'a':
|
||||
for key, value in attrs:
|
||||
if key == 'href' and value.startswith('blender'):
|
||||
remote_platforms.append(value)
|
||||
|
||||
url = 'http://download.blender.org/release/Blender' + bpy.app.version_string.split()[0]
|
||||
parser = AnchorParser()
|
||||
data = urllib.request.urlopen(url).read()
|
||||
parser.feed(str(data))
|
||||
|
||||
print("done", flush=True)
|
||||
|
||||
print("Downloading files (this will take a while depending on your internet connection speed).", flush=True)
|
||||
for i in remote_platforms:
|
||||
src = '/'.join((url, i))
|
||||
dst = os.path.join(lib_path, i)
|
||||
|
||||
dst_dir = '.'.join([i for i in dst.split('.') if i not in {'zip', 'tar', 'bz2'}])
|
||||
if not os.path.exists(dst) and not os.path.exists(dst.split('.')[0]):
|
||||
print("Downloading " + src + "...", end=" ", flush=True)
|
||||
urllib.request.urlretrieve(src, dst)
|
||||
print("done", flush=True)
|
||||
else:
|
||||
print("Reusing existing file: " + dst, flush=True)
|
||||
|
||||
print("Unpacking " + dst + "...", end=" ", flush=True)
|
||||
if os.path.exists(dst_dir):
|
||||
shutil.rmtree(dst_dir)
|
||||
shutil.unpack_archive(dst, dst_dir)
|
||||
print("done", flush=True)
|
||||
|
||||
print("Creating platform from libs...", flush=True)
|
||||
bpy.ops.scene.publish_auto_platforms()
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class PublishAddPlatform(bpy.types.Operator):
|
||||
bl_idname = "scene.publish_add_platform"
|
||||
bl_label = "Add Publish Platform"
|
||||
|
||||
def execute(self, context):
|
||||
a = context.scene.ge_publish_settings.platforms.add()
|
||||
a.name = a.name
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class PublishRemovePlatform(bpy.types.Operator):
|
||||
bl_idname = "scene.publish_remove_platform"
|
||||
bl_label = "Remove Publish Platform"
|
||||
|
||||
def execute(self, context):
|
||||
ps = context.scene.ge_publish_settings
|
||||
if ps.platforms_active < len(ps.platforms):
|
||||
ps.platforms.remove(ps.platforms_active)
|
||||
return {'FINISHED'}
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
||||
# TODO maybe this should display a file browser?
|
||||
class PublishAddAssetPath(bpy.types.Operator):
|
||||
bl_idname = "scene.publish_add_assetpath"
|
||||
bl_label = "Add Asset Path"
|
||||
|
||||
def execute(self, context):
|
||||
a = context.scene.ge_publish_settings.asset_paths.add()
|
||||
a.name = a.name
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class PublishRemoveAssetPath(bpy.types.Operator):
|
||||
bl_idname = "scene.publish_remove_assetpath"
|
||||
bl_label = "Remove Asset Path"
|
||||
|
||||
def execute(self, context):
|
||||
ps = context.scene.ge_publish_settings
|
||||
if ps.asset_paths_active < len(ps.asset_paths):
|
||||
ps.asset_paths.remove(ps.asset_paths_active)
|
||||
return {'FINISHED'}
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
||||
class PUBLISH_MT_platform_specials(bpy.types.Menu):
|
||||
bl_label = "Platform Specials"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator(PublishAutoPlatforms.bl_idname)
|
||||
layout.operator(PublishDownloadPlatforms.bl_idname)
|
||||
|
||||
|
||||
class PlatformSettings(bpy.types.PropertyGroup):
|
||||
name = bpy.props.StringProperty(
|
||||
name = "Platform Name",
|
||||
description = "The name of the platform",
|
||||
default = "Platform",
|
||||
)
|
||||
|
||||
player_path = bpy.props.StringProperty(
|
||||
name = "Player Path",
|
||||
description = "The path to the Blenderplayer to use for this platform",
|
||||
default = "//lib/platform/blenderplayer",
|
||||
subtype = 'FILE_PATH',
|
||||
)
|
||||
|
||||
publish = bpy.props.BoolProperty(
|
||||
name = "Publish",
|
||||
description = "Whether or not to publish to this platform",
|
||||
default = True,
|
||||
)
|
||||
|
||||
|
||||
class AssetPath(bpy.types.PropertyGroup):
|
||||
# TODO This needs a way to be a FILE_PATH or a DIR_PATH
|
||||
name = bpy.props.StringProperty(
|
||||
name = "Asset Path",
|
||||
description = "Path to the asset to be copied",
|
||||
default = "//src",
|
||||
subtype = 'FILE_PATH',
|
||||
)
|
||||
|
||||
overwrite = bpy.props.BoolProperty(
|
||||
name = "Overwrite Asset",
|
||||
description = "Overwrite the asset if it already exists in the destination folder",
|
||||
default = True,
|
||||
)
|
||||
|
||||
|
||||
class PublishSettings(bpy.types.PropertyGroup):
|
||||
output_path = bpy.props.StringProperty(
|
||||
name = "Publish Output",
|
||||
description = "Where to publish the game",
|
||||
default = "//bin/",
|
||||
subtype = 'DIR_PATH',
|
||||
)
|
||||
|
||||
runtime_name = bpy.props.StringProperty(
|
||||
name = "Runtime name",
|
||||
description = "The filename for the created runtime",
|
||||
default = "game",
|
||||
)
|
||||
|
||||
lib_path = bpy.props.StringProperty(
|
||||
name = "Library Path",
|
||||
description = "Directory to search for platforms",
|
||||
default = "//lib/",
|
||||
subtype = 'DIR_PATH',
|
||||
)
|
||||
|
||||
publish_default_platform = bpy.props.BoolProperty(
|
||||
name = "Publish Default Platform",
|
||||
description = "Whether or not to publish the default platform (the Blender install running this addon) when publishing platforms",
|
||||
default = True,
|
||||
)
|
||||
|
||||
|
||||
platforms = bpy.props.CollectionProperty(type=PlatformSettings, name="Platforms")
|
||||
platforms_active = bpy.props.IntProperty()
|
||||
|
||||
asset_paths = bpy.props.CollectionProperty(type=AssetPath, name="Asset Paths")
|
||||
asset_paths_active = bpy.props.IntProperty()
|
||||
|
||||
make_archive = bpy.props.BoolProperty(
|
||||
name = "Make Archive",
|
||||
description = "Create a zip archive of the published game",
|
||||
default = True,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
|
||||
bpy.types.Scene.ge_publish_settings = bpy.props.PointerProperty(type=PublishSettings)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_module(__name__)
|
||||
del bpy.types.Scene.ge_publish_settings
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
|
@ -1,258 +0,0 @@
|
|||
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
bl_info = {
|
||||
"name": "Save As Game Engine Runtime",
|
||||
"author": "Mitchell Stokes (Moguri)",
|
||||
"version": (0, 3, 1),
|
||||
"blender": (2, 61, 0),
|
||||
"location": "File > Export",
|
||||
"description": "Bundle a .blend file with the Blenderplayer",
|
||||
"warning": "",
|
||||
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
|
||||
"Scripts/Game_Engine/Save_As_Runtime",
|
||||
"category": "Game Engine",
|
||||
}
|
||||
|
||||
import bpy
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
|
||||
def CopyPythonLibs(dst, overwrite_lib, report=print):
|
||||
import platform
|
||||
|
||||
# use python module to find pytohn's libpath
|
||||
src = os.path.dirname(platform.__file__)
|
||||
|
||||
# dst points to lib/, but src points to current python's library path, eg:
|
||||
# '/usr/lib/python3.2' vs '/usr/lib'
|
||||
# append python's library dir name to destination, so only python's
|
||||
# libraries would be copied
|
||||
if os.name == 'posix':
|
||||
dst = os.path.join(dst, os.path.basename(src))
|
||||
|
||||
if os.path.exists(src):
|
||||
write = False
|
||||
if os.path.exists(dst):
|
||||
if overwrite_lib:
|
||||
shutil.rmtree(dst)
|
||||
write = True
|
||||
else:
|
||||
write = True
|
||||
if write:
|
||||
shutil.copytree(src, dst, ignore=lambda dir, contents: [i for i in contents if i == '__pycache__'])
|
||||
else:
|
||||
report({'WARNING'}, "Python not found in %r, skipping pythn copy" % src)
|
||||
|
||||
|
||||
def WriteAppleRuntime(player_path, output_path, copy_python, overwrite_lib):
|
||||
# Enforce the extension
|
||||
if not output_path.endswith('.app'):
|
||||
output_path += '.app'
|
||||
|
||||
# Use the system's cp command to preserve some meta-data
|
||||
os.system('cp -R "%s" "%s"' % (player_path, output_path))
|
||||
|
||||
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(output_path, "Contents/Resources/game.blend"),
|
||||
relative_remap=False,
|
||||
compress=False,
|
||||
copy=True,
|
||||
)
|
||||
|
||||
# Python doesn't need to be copied for OS X since it's already inside blenderplayer.app
|
||||
|
||||
|
||||
def WriteRuntime(player_path, output_path, copy_python, overwrite_lib, copy_dlls, report=print):
|
||||
import struct
|
||||
|
||||
# Check the paths
|
||||
if not os.path.isfile(player_path) and not(os.path.exists(player_path) and player_path.endswith('.app')):
|
||||
report({'ERROR'}, "The player could not be found! Runtime not saved")
|
||||
return
|
||||
|
||||
# Check if we're bundling a .app
|
||||
if player_path.endswith('.app'):
|
||||
WriteAppleRuntime(player_path, output_path, copy_python, overwrite_lib)
|
||||
return
|
||||
|
||||
# Enforce "exe" extension on Windows
|
||||
if player_path.endswith('.exe') and not output_path.endswith('.exe'):
|
||||
output_path += '.exe'
|
||||
|
||||
# Get the player's binary and the offset for the blend
|
||||
file = open(player_path, 'rb')
|
||||
player_d = file.read()
|
||||
offset = file.tell()
|
||||
file.close()
|
||||
|
||||
# Create a tmp blend file (Blenderplayer doesn't like compressed blends)
|
||||
tempdir = tempfile.mkdtemp()
|
||||
blend_path = os.path.join(tempdir, bpy.path.clean_name(output_path))
|
||||
bpy.ops.wm.save_as_mainfile(filepath=blend_path,
|
||||
relative_remap=False,
|
||||
compress=False,
|
||||
copy=True,
|
||||
)
|
||||
|
||||
# Get the blend data
|
||||
blend_file = open(blend_path, 'rb')
|
||||
blend_d = blend_file.read()
|
||||
blend_file.close()
|
||||
|
||||
# Get rid of the tmp blend, we're done with it
|
||||
os.remove(blend_path)
|
||||
os.rmdir(tempdir)
|
||||
|
||||
# Create a new file for the bundled runtime
|
||||
output = open(output_path, 'wb')
|
||||
|
||||
# Write the player and blend data to the new runtime
|
||||
print("Writing runtime...", end=" ")
|
||||
output.write(player_d)
|
||||
output.write(blend_d)
|
||||
|
||||
# Store the offset (an int is 4 bytes, so we split it up into 4 bytes and save it)
|
||||
output.write(struct.pack('B', (offset>>24)&0xFF))
|
||||
output.write(struct.pack('B', (offset>>16)&0xFF))
|
||||
output.write(struct.pack('B', (offset>>8)&0xFF))
|
||||
output.write(struct.pack('B', (offset>>0)&0xFF))
|
||||
|
||||
# Stuff for the runtime
|
||||
output.write(b'BRUNTIME')
|
||||
output.close()
|
||||
|
||||
print("done")
|
||||
|
||||
# Make the runtime executable on Linux
|
||||
if os.name == 'posix':
|
||||
os.chmod(output_path, 0o755)
|
||||
|
||||
# Copy bundled Python
|
||||
blender_dir = os.path.dirname(bpy.app.binary_path)
|
||||
runtime_dir = os.path.dirname(output_path)
|
||||
|
||||
if copy_python:
|
||||
print("Copying Python files...", end=" ")
|
||||
py_folder = os.path.join(bpy.app.version_string.split()[0], "python", "lib")
|
||||
dst = os.path.join(runtime_dir, py_folder)
|
||||
CopyPythonLibs(dst, overwrite_lib, report)
|
||||
print("done")
|
||||
|
||||
# And DLLs
|
||||
if copy_dlls:
|
||||
print("Copying DLLs...", end=" ")
|
||||
for file in [i for i in os.listdir(blender_dir) if i.lower().endswith('.dll')]:
|
||||
src = os.path.join(blender_dir, file)
|
||||
dst = os.path.join(runtime_dir, file)
|
||||
shutil.copy2(src, dst)
|
||||
|
||||
print("done")
|
||||
|
||||
from bpy.props import *
|
||||
|
||||
|
||||
class SaveAsRuntime(bpy.types.Operator):
|
||||
bl_idname = "wm.save_as_runtime"
|
||||
bl_label = "Save As Game Engine Runtime"
|
||||
bl_options = {'REGISTER'}
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
# XXX, this line looks suspicious, could be done better?
|
||||
blender_bin_dir = '/' + os.path.join(*bpy.app.binary_path.split('/')[0:-4])
|
||||
ext = '.app'
|
||||
else:
|
||||
blender_bin_path = bpy.app.binary_path
|
||||
blender_bin_dir = os.path.dirname(blender_bin_path)
|
||||
ext = os.path.splitext(blender_bin_path)[-1].lower()
|
||||
|
||||
default_player_path = os.path.join(blender_bin_dir, 'blenderplayer' + ext)
|
||||
player_path = StringProperty(
|
||||
name="Player Path",
|
||||
description="The path to the player to use",
|
||||
default=default_player_path,
|
||||
subtype='FILE_PATH',
|
||||
)
|
||||
filepath = StringProperty(
|
||||
subtype='FILE_PATH',
|
||||
)
|
||||
copy_python = BoolProperty(
|
||||
name="Copy Python",
|
||||
description="Copy bundle Python with the runtime",
|
||||
default=True,
|
||||
)
|
||||
overwrite_lib = BoolProperty(
|
||||
name="Overwrite 'lib' folder",
|
||||
description="Overwrites the lib folder (if one exists) with the bundled Python lib folder",
|
||||
default=False,
|
||||
)
|
||||
|
||||
# Only Windows has dlls to copy
|
||||
if ext == '.exe':
|
||||
copy_dlls = BoolProperty(
|
||||
name="Copy DLLs",
|
||||
description="Copy all needed DLLs with the runtime",
|
||||
default=True,
|
||||
)
|
||||
else:
|
||||
copy_dlls = False
|
||||
|
||||
def execute(self, context):
|
||||
import time
|
||||
start_time = time.clock()
|
||||
print("Saving runtime to %r" % self.filepath)
|
||||
WriteRuntime(self.player_path,
|
||||
self.filepath,
|
||||
self.copy_python,
|
||||
self.overwrite_lib,
|
||||
self.copy_dlls,
|
||||
self.report,
|
||||
)
|
||||
print("Finished in %.4fs" % (time.clock()-start_time))
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
if not self.filepath:
|
||||
ext = '.app' if sys.platform == 'darwin' else os.path.splitext(bpy.app.binary_path)[-1]
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ext)
|
||||
|
||||
wm = context.window_manager
|
||||
wm.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(SaveAsRuntime.bl_idname)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
|
||||
bpy.types.INFO_MT_file_export.append(menu_func)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_module(__name__)
|
||||
|
||||
bpy.types.INFO_MT_file_export.remove(menu_func)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
|
@ -929,10 +929,6 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper):
|
|||
tex = self.create_image_textures(context, img_spec)
|
||||
material = self.create_material_for_texture(tex)
|
||||
|
||||
# Game Engine Material Settings
|
||||
material.game_settings.use_backface_culling = False
|
||||
material.game_settings.alpha_blend = 'ALPHA'
|
||||
|
||||
# Create and position plane object
|
||||
plane = self.create_image_plane(context, material.name, img_spec)
|
||||
|
||||
|
|
|
@ -805,9 +805,6 @@ class VIEW3D_OT_show_mat_preview(Operator):
|
|||
if is_opaque:
|
||||
col.separator()
|
||||
col.prop(mat, "alpha")
|
||||
col.separator()
|
||||
col.label("Viewport Alpha:")
|
||||
col.prop(mat.game_settings, "alpha_blend", text="")
|
||||
layout.separator()
|
||||
else:
|
||||
other_render = ("*Unavailable with this Renderer*" if not c_render_engine("Both")
|
||||
|
|
|
@ -242,7 +242,6 @@ url_manual_mapping = (
|
|||
("bpy.types.cyclesrendersettings*", "render/cycles/settings/index.html#bpy-types-cyclesrendersettings"),
|
||||
("bpy.types.datatransfermodifier*", "modeling/modifiers/modify/data_transfer.html#bpy-types-datatransfermodifier"),
|
||||
("bpy.types.dynamicpaintmodifier*", "physics/dynamic_paint/index.html#bpy-types-dynamicpaintmodifier"),
|
||||
("bpy.types.expressioncontroller*", "game_engine/logic/controllers/types/expression.html#bpy-types-expressioncontroller"),
|
||||
("bpy.types.ffmpegsettings.audio*", "render/output/video.html#bpy-types-ffmpegsettings-audio"),
|
||||
("bpy.types.followpathconstraint*", "rigging/constraints/relationship/follow_path.html#bpy-types-followpathconstraint"),
|
||||
("bpy.types.gaussianblursequence*", "editors/vse/sequencer/strips/effects/blur.html#bpy-types-gaussianblursequence"),
|
||||
|
@ -334,8 +333,6 @@ url_manual_mapping = (
|
|||
("bpy.types.compositornodemask*", "compositing/types/input/mask.html#bpy-types-compositornodemask"),
|
||||
("bpy.types.compositornodemath*", "compositing/types/converter/math.html#bpy-types-compositornodemath"),
|
||||
("bpy.types.compositornodetime*", "compositing/types/input/time.html#bpy-types-compositornodetime"),
|
||||
("bpy.types.constraintactuator*", "game_engine/logic/actuators/types/constraint.html#bpy-types-constraintactuator"),
|
||||
("bpy.types.editobjectactuator*", "game_engine/logic/actuators/types/edit_object.html#bpy-types-editobjectactuator"),
|
||||
("bpy.types.fluidfluidsettings*", "physics/fluid/types/fluid_object.html#bpy-types-fluidfluidsettings"),
|
||||
("bpy.types.fmodifiergenerator*", "editors/graph_editor/fcurves/fmodifiers.html#bpy-types-fmodifiergenerator"),
|
||||
("bpy.types.freestylelinestyle*", "render/freestyle/parameter_editor/line_style/index.html#bpy-types-freestylelinestyle"),
|
||||
|
@ -362,7 +359,6 @@ url_manual_mapping = (
|
|||
("bpy.types.shrinkwrapmodifier*", "modeling/modifiers/deform/shrinkwrap.html#bpy-types-shrinkwrapmodifier"),
|
||||
("bpy.types.splineikconstraint*", "rigging/constraints/tracking/spline_ik.html#bpy-types-splineikconstraint"),
|
||||
("bpy.types.texturenodetexture*", "render/blender_render/textures/nodes/types/input/texture.html#bpy-types-texturenodetexture"),
|
||||
("bpy.types.visibilityactuator*", "game_engine/logic/actuators/types/visibility.html#bpy-types-visibilityactuator"),
|
||||
("bpy.ops.anim.keyframe_clear*", "animation/keyframes/editing.html#bpy-ops-anim-keyframe-clear"),
|
||||
("bpy.ops.curve.primitive*add*", "modeling/curves/primitives.html#bpy-ops-curve-primitive-add"),
|
||||
("bpy.ops.mesh.duplicate_move*", "modeling/meshes/editing/duplicating/duplicate.html#bpy-ops-mesh-duplicate-move"),
|
||||
|
@ -418,11 +414,9 @@ url_manual_mapping = (
|
|||
("bpy.ops.transform.tosphere*", "modeling/meshes/editing/transform/to_sphere.html#bpy-ops-transform-tosphere"),
|
||||
("bpy.types.actionconstraint*", "rigging/constraints/relationship/action.html#bpy-types-actionconstraint"),
|
||||
("bpy.types.addonpreferences*", "preferences/addons.html#bpy-types-addonpreferences"),
|
||||
("bpy.types.armatureactuator*", "game_engine/logic/actuators/types/armature.html#bpy-types-armatureactuator"),
|
||||
("bpy.types.armaturemodifier*", "modeling/modifiers/deform/armature.html#bpy-types-armaturemodifier"),
|
||||
("bpy.types.displacemodifier*", "modeling/modifiers/deform/displace.html#bpy-types-displacemodifier"),
|
||||
("bpy.types.displaysafeareas*", "render/blender_render/camera/object_data.html#bpy-types-displaysafeareas"),
|
||||
("bpy.types.filter2dactuator*", "game_engine/logic/actuators/types/2d_filters.html#bpy-types-filter2dactuator"),
|
||||
("bpy.types.fmodifierstepped*", "editors/graph_editor/fcurves/fmodifiers.html#bpy-types-fmodifierstepped"),
|
||||
("bpy.types.freestylelineset*", "render/freestyle/parameter_editor/line_set.html#bpy-types-freestylelineset"),
|
||||
("bpy.types.material.ambient*", "render/blender_render/materials/properties/shading.html#bpy-types-material-ambient"),
|
||||
|
@ -434,8 +428,6 @@ url_manual_mapping = (
|
|||
("bpy.types.object.use_extra*", "editors/3dview/object/properties/relations/extras.html#bpy-types-object-use-extra"),
|
||||
("bpy.types.overdropsequence*", "editors/vse/sequencer/strips/effects/alpha_over_under_overdrop.html#bpy-types-overdropsequence"),
|
||||
("bpy.types.particlesettings*", "physics/particles/index.html#bpy-types-particlesettings"),
|
||||
("bpy.types.propertyactuator*", "game_engine/logic/actuators/types/property.html#bpy-types-propertyactuator"),
|
||||
("bpy.types.pythoncontroller*", "game_engine/logic/controllers/types/python.html#bpy-types-pythoncontroller"),
|
||||
("bpy.types.scenerenderlayer*", "render/cycles/settings/scene/render_layers/layers.html#bpy-types-scenerenderlayer"),
|
||||
("bpy.types.sequencemodifier*", "editors/vse/sequencer/properties/modifiers.html#bpy-types-sequencemodifier"),
|
||||
("bpy.types.shadernodeinvert*", "render/cycles/nodes/types/color/invert.html#bpy-types-shadernodeinvert"),
|
||||
|
@ -449,7 +441,6 @@ url_manual_mapping = (
|
|||
("bpy.types.spacegrapheditor*", "editors/graph_editor/index.html#bpy-types-spacegrapheditor"),
|
||||
("bpy.types.spacelogiceditor*", "editors/logic_editor.html#bpy-types-spacelogiceditor"),
|
||||
("bpy.types.sphfluidsettings*", "physics/fluid/index.html#bpy-types-sphfluidsettings"),
|
||||
("bpy.types.steeringactuator*", "game_engine/logic/actuators/types/steering.html#bpy-types-steeringactuator"),
|
||||
("bpy.types.subtractsequence*", "editors/vse/sequencer/strips/effects/subtract.html#bpy-types-subtractsequence"),
|
||||
("bpy.types.texturenodegroup*", "render/blender_render/textures/nodes/types/groups.html#bpy-types-texturenodegroup"),
|
||||
("bpy.types.texturenodeimage*", "render/blender_render/textures/nodes/types/input/image.html#bpy-types-texturenodeimage"),
|
||||
|
@ -468,7 +459,6 @@ url_manual_mapping = (
|
|||
("bpy.ops.uv.remove_doubles*", "editors/uv_image/uv_editing/layout_editing.html#bpy-ops-uv-remove-doubles"),
|
||||
("bpy.types.backgroundimage*", "editors/3dview/properties/background_images.html#bpy-types-backgroundimage"),
|
||||
("bpy.types.booleanmodifier*", "modeling/modifiers/generate/booleans.html#bpy-types-booleanmodifier"),
|
||||
("bpy.types.collisionsensor*", "game_engine/logic/sensors/types/collision.html#bpy-types-collisionsensor"),
|
||||
("bpy.types.constraint.mute*", "rigging/constraints/interface/header.html#bpy-types-constraint-mute"),
|
||||
("bpy.types.explodemodifier*", "modeling/modifiers/simulate/explode.html#bpy-types-explodemodifier"),
|
||||
("bpy.types.fcurvemodifiers*", "editors/graph_editor/fcurves/fmodifiers.html#bpy-types-fcurvemodifiers"),
|
||||
|
@ -478,7 +468,6 @@ url_manual_mapping = (
|
|||
("bpy.types.fmodifierlimits*", "editors/graph_editor/fcurves/fmodifiers.html#bpy-types-fmodifierlimits"),
|
||||
("bpy.types.gpussaosettings*", "editors/3dview/properties/shading.html#bpy-types-gpussaosettings"),
|
||||
("bpy.types.latticemodifier*", "modeling/modifiers/deform/lattice.html#bpy-types-latticemodifier"),
|
||||
("bpy.types.messageactuator*", "game_engine/logic/actuators/types/message.html#bpy-types-messageactuator"),
|
||||
("bpy.types.musgravetexture*", "render/blender_render/textures/types/procedural/musgrave.html#bpy-types-musgravetexture"),
|
||||
("bpy.types.object.location*", "editors/3dview/object/properties/transforms.html#bpy-types-object-location"),
|
||||
("bpy.types.object.rotation*", "editors/3dview/object/properties/transforms.html#bpy-types-object-rotation"),
|
||||
|
@ -502,28 +491,18 @@ url_manual_mapping = (
|
|||
("bpy.ops.transform.resize*", "editors/3dview/object/editing/transform/basics.html#bpy-ops-transform-resize"),
|
||||
("bpy.ops.transform.rotate*", "editors/3dview/object/editing/transform/basics.html#bpy-ops-transform-rotate"),
|
||||
("bpy.ops.view3d.localview*", "editors/3dview/navigate/views.html#bpy-ops-view3d-localview"),
|
||||
("bpy.types.actionactuator*", "game_engine/logic/actuators/types/action.html#bpy-types-actionactuator"),
|
||||
("bpy.types.actuatorsensor*", "game_engine/logic/sensors/types/actuator.html#bpy-types-actuatorsensor"),
|
||||
("bpy.types.armaturesensor*", "game_engine/logic/sensors/types/armature.html#bpy-types-armaturesensor"),
|
||||
("bpy.types.cameraactuator*", "game_engine/logic/actuators/types/camera.html#bpy-types-cameraactuator"),
|
||||
("bpy.types.curvesmodifier*", "editors/vse/sequencer/properties/modifiers.html#bpy-types-curvesmodifier"),
|
||||
("bpy.types.effectsequence*", "editors/vse/sequencer/properties/filter.html#bpy-types-effectsequence"),
|
||||
("bpy.types.ffmpegsettings*", "render/output/video.html#bpy-types-ffmpegsettings"),
|
||||
("bpy.types.fmodifiernoise*", "editors/graph_editor/fcurves/fmodifiers.html#bpy-types-fmodifiernoise"),
|
||||
("bpy.types.gpudofsettings*", "editors/3dview/properties/shading.html#bpy-types-gpudofsettings"),
|
||||
("bpy.types.joysticksensor*", "game_engine/logic/sensors/types/joystick.html#bpy-types-joysticksensor"),
|
||||
("bpy.types.keyboardsensor*", "game_engine/logic/sensors/types/keyboard.html#bpy-types-keyboardsensor"),
|
||||
("bpy.types.materialstrand*", "render/blender_render/materials/properties/strands.html#bpy-types-materialstrand"),
|
||||
("bpy.types.materialvolume*", "render/blender_render/materials/special_effects/volume.html#bpy-types-materialvolume"),
|
||||
("bpy.types.mirrormodifier*", "modeling/modifiers/generate/mirror.html#bpy-types-mirrormodifier"),
|
||||
("bpy.types.movieclipproxy*", "editors/movie_clip_editor/properties/proxy.html#bpy-types-movieclipproxy"),
|
||||
("bpy.types.object.up_axis*", "editors/3dview/object/properties/relations/extras.html#bpy-types-object-up-axis"),
|
||||
("bpy.types.objectactuator*", "game_engine/logic/actuators/types/motion.html#bpy-types-objectactuator"),
|
||||
("bpy.types.parentactuator*", "game_engine/logic/actuators/types/parent.html#bpy-types-parentactuator"),
|
||||
("bpy.types.particlesystem*", "physics/particles/index.html#bpy-types-particlesystem"),
|
||||
("bpy.types.particletarget*", "physics/particles/emitter/physics/keyed.html#bpy-types-particletarget"),
|
||||
("bpy.types.propertysensor*", "game_engine/logic/sensors/types/property.html#bpy-types-propertysensor"),
|
||||
("bpy.types.randomactuator*", "game_engine/logic/actuators/types/random.html#bpy-types-randomactuator"),
|
||||
("bpy.types.remeshmodifier*", "modeling/modifiers/generate/remesh.html#bpy-types-remeshmodifier"),
|
||||
("bpy.types.rendersettings*", "render/index.html#bpy-types-rendersettings"),
|
||||
("bpy.types.rigidbodyworld*", "physics/rigid_body/world.html#bpy-types-rigidbodyworld"),
|
||||
|
@ -557,9 +536,7 @@ url_manual_mapping = (
|
|||
("bpy.types.gpufxsettings*", "editors/3dview/properties/shading.html#bpy-types-gpufxsettings"),
|
||||
("bpy.types.imagesequence*", "editors/vse/sequencer/strips/image_movie.html#bpy-types-imagesequence"),
|
||||
("bpy.types.marbletexture*", "render/blender_render/textures/types/procedural/marble.html#bpy-types-marbletexture"),
|
||||
("bpy.types.messagesensor*", "game_engine/logic/sensors/types/message.html#bpy-types-messagesensor"),
|
||||
("bpy.types.modifier.show*", "modeling/modifiers/introduction.html#bpy-types-modifier-show"),
|
||||
("bpy.types.mouseactuator*", "game_engine/logic/actuators/types/mouse.html#bpy-types-mouseactuator"),
|
||||
("bpy.types.moviesequence*", "editors/vse/sequencer/strips/image_movie.html#bpy-types-moviesequence"),
|
||||
("bpy.types.movietracking*", "editors/movie_clip_editor/tracking/index.html#bpy-types-movietracking"),
|
||||
("bpy.types.object.layers*", "editors/3dview/object/properties/relations/layers.html#bpy-types-object-layers"),
|
||||
|
@ -567,18 +544,15 @@ url_manual_mapping = (
|
|||
("bpy.types.oceanmodifier*", "modeling/modifiers/simulate/ocean.html#bpy-types-oceanmodifier"),
|
||||
("bpy.types.particlebrush*", "physics/particles/mode.html#bpy-types-particlebrush"),
|
||||
("bpy.types.scene.gravity*", "physics/gravity.html#bpy-types-scene-gravity"),
|
||||
("bpy.types.sceneactuator*", "game_engine/logic/actuators/types/scene.html#bpy-types-sceneactuator"),
|
||||
("bpy.types.scenesequence*", "editors/vse/sequencer/strips/scene.html#bpy-types-scenesequence"),
|
||||
("bpy.types.screwmodifier*", "modeling/modifiers/generate/screw.html#bpy-types-screwmodifier"),
|
||||
("bpy.types.sequenceproxy*", "editors/vse/sequencer/properties/proxy_timecode.html#bpy-types-sequenceproxy"),
|
||||
("bpy.types.shadernodergb*", "render/cycles/nodes/types/input/rgb.html#bpy-types-shadernodergb"),
|
||||
("bpy.types.smokemodifier*", "physics/smoke/index.html#bpy-types-smokemodifier"),
|
||||
("bpy.types.soundactuator*", "game_engine/logic/actuators/types/sound.html#bpy-types-soundactuator"),
|
||||
("bpy.types.soundsequence*", "editors/vse/sequencer/strips/audio.html#bpy-types-soundsequence"),
|
||||
("bpy.types.spaceoutliner*", "editors/outliner.html#bpy-types-spaceoutliner"),
|
||||
("bpy.types.spacetimeline*", "editors/timeline.html#bpy-types-spacetimeline"),
|
||||
("bpy.types.spaceuveditor*", "editors/uv_image/uv_editing/index.html#bpy-types-spaceuveditor"),
|
||||
("bpy.types.stateactuator*", "game_engine/logic/actuators/types/state.html#bpy-types-stateactuator"),
|
||||
("bpy.types.stuccitexture*", "render/blender_render/textures/types/procedural/stucci.html#bpy-types-stuccitexture"),
|
||||
("bpy.types.windowmanager*", "interface/index.html#bpy-types-windowmanager"),
|
||||
("bpy.types.worldlighting*", "render/blender_render/world/ambient_occlusion.html#bpy-types-worldlighting"),
|
||||
|
@ -586,12 +560,10 @@ url_manual_mapping = (
|
|||
("bpy.ops.object.convert*", "editors/3dview/object/editing/introduction.html#bpy-ops-object-convert"),
|
||||
("bpy.ops.object.speaker*", "render/audio/speaker.html#bpy-ops-object-speaker"),
|
||||
("bpy.ops.transform.bend*", "modeling/meshes/editing/transform/bend.html#bpy-ops-transform-bend"),
|
||||
("bpy.types.alwayssensor*", "game_engine/logic/sensors/types/always.html#bpy-types-alwayssensor"),
|
||||
("bpy.types.bakesettings*", "render/cycles/baking.html#bpy-types-bakesettings"),
|
||||
("bpy.types.blendtexture*", "render/blender_render/textures/types/procedural/blend.html#bpy-types-blendtexture"),
|
||||
("bpy.types.castmodifier*", "modeling/modifiers/deform/cast.html#bpy-types-castmodifier"),
|
||||
("bpy.types.colormanaged*", "render/post_process/color_management.html#bpy-types-colormanaged"),
|
||||
("bpy.types.gameactuator*", "game_engine/logic/actuators/types/game.html#bpy-types-gameactuator"),
|
||||
("bpy.types.glowsequence*", "editors/vse/sequencer/strips/effects/glow.html#bpy-types-glowsequence"),
|
||||
("bpy.types.gpencilbrush*", "interface/grease_pencil/drawing/brushes.html#bpy-types-gpencilbrush"),
|
||||
("bpy.types.greasepencil*", "interface/grease_pencil/index.html#bpy-types-greasepencil"),
|
||||
|
@ -609,7 +581,6 @@ url_manual_mapping = (
|
|||
("bpy.types.object.scale*", "editors/3dview/object/properties/transforms.html#bpy-types-object-scale"),
|
||||
("bpy.types.oceantexture*", "render/blender_render/textures/types/procedural/ocean.html#bpy-types-oceantexture"),
|
||||
("bpy.types.particleedit*", "physics/particles/mode.html#bpy-types-particleedit"),
|
||||
("bpy.types.randomsensor*", "game_engine/logic/sensors/types/random.html#bpy-types-randomsensor"),
|
||||
("bpy.types.scene.camera*", "data_system/scenes/properties.html#bpy-types-scene-camera"),
|
||||
("bpy.types.sequencecrop*", "editors/vse/sequencer/properties/input.html#bpy-types-sequencecrop"),
|
||||
("bpy.types.skinmodifier*", "modeling/modifiers/generate/skin.html#bpy-types-skinmodifier"),
|
||||
|
@ -627,14 +598,11 @@ url_manual_mapping = (
|
|||
("bpy.ops.wm.properties*", "data_system/custom_properties.html#bpy-ops-wm-properties"),
|
||||
("bpy.types.addsequence*", "editors/vse/sequencer/strips/effects/add.html#bpy-types-addsequence"),
|
||||
("bpy.types.consoleline*", "editors/python_console.html#bpy-types-consoleline"),
|
||||
("bpy.types.delaysensor*", "game_engine/logic/sensors/types/delay.html#bpy-types-delaysensor"),
|
||||
("bpy.types.meshstatvis*", "modeling/meshes/mesh_analysis.html#bpy-types-meshstatvis"),
|
||||
("bpy.types.mousesensor*", "game_engine/logic/sensors/types/mouse.html#bpy-types-mousesensor"),
|
||||
("bpy.types.nodesetting*", "editors/node_editor/nodes/parts.html#bpy-types-nodesetting"),
|
||||
("bpy.types.object.lock*", "editors/3dview/object/properties/transforms.html#bpy-types-object-lock"),
|
||||
("bpy.types.object.show*", "editors/3dview/object/properties/display.html#bpy-types-object-show"),
|
||||
("bpy.types.particlekey*", "physics/particles/emitter/physics/keyed.html#bpy-types-particlekey"),
|
||||
("bpy.types.radarsensor*", "game_engine/logic/sensors/types/radar.html#bpy-types-radarsensor"),
|
||||
("bpy.types.renderlayer*", "render/post_process/layers.html#bpy-types-renderlayer"),
|
||||
("bpy.types.spaceview3d*", "editors/3dview/index.html#bpy-types-spaceview3d"),
|
||||
("bpy.types.uipopupmenu*", "interface/controls/buttons/menus.html#bpy-types-uipopupmenu"),
|
||||
|
@ -651,8 +619,6 @@ url_manual_mapping = (
|
|||
("bpy.types.bpy_struct*", "data_system/custom_properties.html#bpy-types-bpy-struct"),
|
||||
("bpy.types.compositor*", "compositing/index.html#bpy-types-compositor"),
|
||||
("bpy.types.constraint*", "rigging/constraints/index.html#bpy-types-constraint"),
|
||||
("bpy.types.controller*", "game_engine/logic/controllers/index.html#bpy-types-controller"),
|
||||
("bpy.types.nearsensor*", "game_engine/logic/sensors/types/near.html#bpy-types-nearsensor"),
|
||||
("bpy.types.nodesocket*", "editors/node_editor/nodes/parts.html#bpy-types-nodesocket"),
|
||||
("bpy.types.pointcache*", "physics/baking.html#bpy-types-pointcache"),
|
||||
("bpy.types.renderpass*", "render/blender_render/settings/passes.html#bpy-types-renderpass"),
|
||||
|
@ -672,7 +638,6 @@ url_manual_mapping = (
|
|||
("bpy.types.nodeframe*", "editors/node_editor/nodes/frame.html#bpy-types-nodeframe"),
|
||||
("bpy.types.nodegroup*", "editors/node_editor/nodes/groups.html#bpy-types-nodegroup"),
|
||||
("bpy.types.pointlamp*", "render/blender_render/lighting/lamps/point.html#bpy-types-pointlamp"),
|
||||
("bpy.types.raysensor*", "game_engine/logic/sensors/types/ray.html#bpy-types-raysensor"),
|
||||
("bpy.types.spaceinfo*", "editors/info/index.html#bpy-types-spaceinfo"),
|
||||
("bpy.types.textcurve*", "modeling/texts/index.html#bpy-types-textcurve"),
|
||||
("bpy.types.uipiemenu*", "interface/controls/buttons/menus.html#bpy-types-uipiemenu"),
|
||||
|
@ -682,14 +647,12 @@ url_manual_mapping = (
|
|||
("bpy.ops.mesh.noise*", "modeling/meshes/editing/transform/noise.html#bpy-ops-mesh-noise"),
|
||||
("bpy.ops.mesh.screw*", "modeling/meshes/editing/duplicating/screw.html#bpy-ops-mesh-screw"),
|
||||
("bpy.ops.safe_areas*", "render/blender_render/camera/object_data.html#bpy-ops-safe-areas"),
|
||||
("bpy.types.actuator*", "game_engine/logic/actuators/index.html#bpy-types-actuator"),
|
||||
("bpy.types.arealamp*", "render/blender_render/lighting/lamps/area/index.html#bpy-types-arealamp"),
|
||||
("bpy.types.armature*", "rigging/armatures/index.html#bpy-types-armature"),
|
||||
("bpy.types.editbone*", "rigging/armatures/bones/editing/index.html#bpy-types-editbone"),
|
||||
("bpy.types.hemilamp*", "render/blender_render/lighting/lamps/hemi.html#bpy-types-hemilamp"),
|
||||
("bpy.types.keyframe*", "animation/keyframes/index.html#bpy-types-keyframe"),
|
||||
("bpy.types.linesets*", "render/freestyle/parameter_editor/line_set.html#bpy-types-linesets"),
|
||||
("bpy.types.lodlevel*", "game_engine/settings/object.html#bpy-types-lodlevel"),
|
||||
("bpy.types.material*", "render/blender_render/materials/index.html#bpy-types-material"),
|
||||
("bpy.types.metaball*", "modeling/metas/index.html#bpy-types-metaball"),
|
||||
("bpy.types.modifier*", "modeling/modifiers/index.html#bpy-types-modifier"),
|
||||
|
@ -733,7 +696,6 @@ url_manual_mapping = (
|
|||
("bpy.types.render*", "render/index.html#bpy-types-render"),
|
||||
("bpy.types.screen*", "interface/window_system/screens.html#bpy-types-screen"),
|
||||
("bpy.types.sculpt*", "sculpt_paint/sculpting/index.html#bpy-types-sculpt"),
|
||||
("bpy.types.sensor*", "game_engine/logic/sensors/index.html#bpy-types-sensor"),
|
||||
("bpy.types.shader*", "render/cycles/nodes/types/shaders/index.html#bpy-types-shader"),
|
||||
("bpy.types.window*", "interface/index.html#bpy-types-window"),
|
||||
("bpy.ops.buttons*", "interface/index.html#bpy-ops-buttons"),
|
||||
|
@ -790,7 +752,6 @@ url_manual_mapping = (
|
|||
("bpy.ops.graph*", "editors/graph_editor/index.html#bpy-ops-graph"),
|
||||
("bpy.ops.group*", "editors/3dview/object/properties/relations/groups.html#bpy-ops-group"),
|
||||
("bpy.ops.image*", "data_system/files/media/image_formats.html#bpy-ops-image"),
|
||||
("bpy.ops.logic*", "game_engine/logic/index.html#bpy-ops-logic"),
|
||||
("bpy.ops.mball*", "modeling/metas/index.html#bpy-ops-mball"),
|
||||
("bpy.ops.paint*", "sculpt_paint/index.html#bpy-ops-paint"),
|
||||
("bpy.ops.scene*", "data_system/scenes/index.html#bpy-ops-scene"),
|
||||
|
|
|
@ -35,7 +35,7 @@ ADDRESS_TEST_TIMEOUT = 30
|
|||
|
||||
def base_poll(cls, context):
|
||||
rd = context.scene.render
|
||||
return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
|
||||
def init_file():
|
||||
|
@ -96,7 +96,7 @@ class NetRenderButtonsPanel():
|
|||
@classmethod
|
||||
def poll(cls, context):
|
||||
rd = context.scene.render
|
||||
return rd.engine == 'NET_RENDER' and rd.use_game_engine == False
|
||||
return rd.engine == 'NET_RENDER'
|
||||
|
||||
# Setting panel, use in the scene for now.
|
||||
class RENDER_PT_network_settings(NetRenderButtonsPanel, bpy.types.Panel):
|
||||
|
|
|
@ -158,15 +158,12 @@ del properties_data_modifier
|
|||
from bl_ui import properties_material
|
||||
for member in dir(properties_material):
|
||||
subclass = getattr(properties_material, member)
|
||||
if subclass not in (properties_material.MATERIAL_PT_transp_game,
|
||||
properties_material.MATERIAL_PT_game_settings,
|
||||
properties_material.MATERIAL_PT_physics):
|
||||
try:
|
||||
#mat=context.material
|
||||
#if mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes):
|
||||
subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
#mat=context.material
|
||||
#if mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes):
|
||||
subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
|
||||
except:
|
||||
pass
|
||||
del properties_material
|
||||
|
||||
|
||||
|
@ -238,7 +235,7 @@ class RenderButtonsPanel():
|
|||
@classmethod
|
||||
def poll(cls, context):
|
||||
rd = context.scene.render
|
||||
return (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
class ModifierButtonsPanel():
|
||||
bl_space_type = 'PROPERTIES'
|
||||
|
@ -250,7 +247,7 @@ class ModifierButtonsPanel():
|
|||
def poll(cls, context):
|
||||
mods = context.object.modifiers
|
||||
rd = context.scene.render
|
||||
return mods and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return mods and (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
class MaterialButtonsPanel():
|
||||
bl_space_type = 'PROPERTIES'
|
||||
|
@ -262,7 +259,7 @@ class MaterialButtonsPanel():
|
|||
def poll(cls, context):
|
||||
mat = context.material
|
||||
rd = context.scene.render
|
||||
return mat and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return mat (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
|
||||
class TextureButtonsPanel():
|
||||
|
@ -275,7 +272,7 @@ class TextureButtonsPanel():
|
|||
def poll(cls, context):
|
||||
tex = context.texture
|
||||
rd = context.scene.render
|
||||
return tex and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return tex and (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
# class TextureTypePanel(TextureButtonsPanel):
|
||||
|
||||
|
@ -296,7 +293,7 @@ class ObjectButtonsPanel():
|
|||
def poll(cls, context):
|
||||
obj = context.object
|
||||
rd = context.scene.render
|
||||
return obj and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return obj and (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
class CameraDataButtonsPanel():
|
||||
bl_space_type = 'PROPERTIES'
|
||||
|
@ -308,7 +305,7 @@ class CameraDataButtonsPanel():
|
|||
def poll(cls, context):
|
||||
cam = context.camera
|
||||
rd = context.scene.render
|
||||
return cam and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return cam and (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
class WorldButtonsPanel():
|
||||
bl_space_type = 'PROPERTIES'
|
||||
|
@ -320,7 +317,7 @@ class WorldButtonsPanel():
|
|||
def poll(cls, context):
|
||||
wld = context.world
|
||||
rd = context.scene.render
|
||||
return wld and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return wld and (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
class TextButtonsPanel():
|
||||
bl_space_type = 'TEXT_EDITOR'
|
||||
|
@ -332,7 +329,7 @@ class TextButtonsPanel():
|
|||
def poll(cls, context):
|
||||
text = context.space_data
|
||||
rd = context.scene.render
|
||||
return text and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return text and (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
from bl_ui import properties_data_mesh
|
||||
# These panels are kept
|
||||
|
|
|
@ -383,11 +383,6 @@ def obCol(ob, active, context):
|
|||
ob.color = active.color
|
||||
|
||||
|
||||
def obMas(ob, active, context):
|
||||
ob.game.mass = active.game.mass
|
||||
return('INFO', "Mass copied")
|
||||
|
||||
|
||||
def obLok(ob, active, context):
|
||||
for index, state in enumerate(active.lock_location):
|
||||
ob.lock_location[index] = state
|
||||
|
@ -509,8 +504,6 @@ object_copies = (
|
|||
"Copy Dupli from Active to Selected", obDup),
|
||||
('obj_col', "Object Color",
|
||||
"Copy Object Color from Active to Selected", obCol),
|
||||
('obj_mas', "Mass",
|
||||
"Copy Mass from Active to Selected", obMas),
|
||||
# ('obj_dmp', "Damping",
|
||||
# "Copy Damping from Active to Selected"),
|
||||
# ('obj_all', "All Physical Attributes",
|
||||
|
|
|
@ -807,7 +807,6 @@ class VIEW3D_MT_Object(Menu):
|
|||
layout.menu("VIEW3D_MT_object_track")
|
||||
layout.menu("VIEW3D_MT_object_animation")
|
||||
UseSeparator(self, context)
|
||||
layout.menu("VIEW3D_MT_object_game")
|
||||
layout.menu("VIEW3D_MT_object_showhide")
|
||||
UseSeparator(self, context)
|
||||
layout.operator_menu_enum("object.convert", "target")
|
||||
|
|
Loading…
Reference in New Issue