Upgrading armory into b2.8 engine

This commit is contained in:
luboslenco 2018-05-24 22:16:28 +02:00
parent 2069bd2e75
commit e48b16d3d4
23 changed files with 428 additions and 1126 deletions

View file

@ -263,17 +263,17 @@ class Inc {
#end #end
} }
public static inline function getRenderCaptureFormat():String { // public static inline function getRenderCaptureFormat():String {
#if (rp_rendercapture_format == "8bit") // #if (rp_rendercapture_format == "8bit")
return "RGBA32"; // return "RGBA32";
#elseif (rp_rendercapture_format == "16bit") // #elseif (rp_rendercapture_format == "16bit")
return "RGBA64"; // return "RGBA64";
#elseif (rp_rendercapture_format == "32bit") // #elseif (rp_rendercapture_format == "32bit")
return "RGBA128"; // return "RGBA128";
#else // #else
return "RGBA32"; // return "RGBA32";
#end // #end
} // }
#if (rp_gi == "Voxel GI") #if (rp_gi == "Voxel GI")
public static function computeVoxelsBegin() { public static function computeVoxelsBegin() {

View file

@ -183,16 +183,16 @@ class RenderPathDeferred {
} }
#end #end
#if rp_rendercapture // #if rp_rendercapture
{ // {
var t = new RenderTargetRaw(); // var t = new RenderTargetRaw();
t.name = "capture"; // t.name = "capture";
t.width = 0; // t.width = 0;
t.height = 0; // t.height = 0;
t.format = Inc.getRenderCaptureFormat(); // t.format = Inc.getRenderCaptureFormat();
path.createRenderTarget(t); // path.createRenderTarget(t);
} // }
#end // #end
#if rp_compositornodes #if rp_compositornodes
{ {
@ -852,22 +852,22 @@ class RenderPathDeferred {
#if (rp_supersampling == 4) #if (rp_supersampling == 4)
{ {
#if rp_rendercapture // #if rp_rendercapture
// TODO: ss4 + capture broken // TODO: ss4 + capture broken
var finalTarget = "capture"; // var finalTarget = "capture";
#else // #else
var finalTarget = ""; var finalTarget = "";
#end // #end
path.setTarget(finalTarget); path.setTarget(finalTarget);
path.bindTarget(framebuffer, "tex"); path.bindTarget(framebuffer, "tex");
path.drawShader("shader_datas/supersample_resolve/supersample_resolve"); path.drawShader("shader_datas/supersample_resolve/supersample_resolve");
} }
#elseif (rp_rendercapture) // #elseif (rp_rendercapture)
{ // {
path.setTarget("capture"); // path.setTarget("capture");
path.bindTarget(framebuffer, "tex"); // path.bindTarget(framebuffer, "tex");
path.drawShader("shader_datas/copy_pass/copy_pass"); // path.drawShader("shader_datas/copy_pass/copy_pass");
} // }
#end #end
} }
#end #end

View file

@ -52,19 +52,19 @@ class RenderPathForward {
} }
#end #end
#if rp_rendercapture // #if rp_rendercapture
{ // {
var t = new RenderTargetRaw(); // var t = new RenderTargetRaw();
t.name = "capture"; // t.name = "capture";
t.width = 0; // t.width = 0;
t.height = 0; // t.height = 0;
t.format = Inc.getRenderCaptureFormat(); // t.format = Inc.getRenderCaptureFormat();
path.createRenderTarget(t); // path.createRenderTarget(t);
#if rp_compositornodes // #if rp_compositornodes
path.loadShader("shader_datas/copy_pass/copy_pass"); // path.loadShader("shader_datas/copy_pass/copy_pass");
#end // #end
} // }
#end // #end
#if ((rp_supersampling == 4) || (rp_antialiasing == "SMAA") || (rp_antialiasing == "TAA")) #if ((rp_supersampling == 4) || (rp_antialiasing == "SMAA") || (rp_antialiasing == "TAA"))
{ {
@ -488,21 +488,21 @@ class RenderPathForward {
#if (rp_supersampling == 4) #if (rp_supersampling == 4)
{ {
#if rp_rendercapture // #if rp_rendercapture
var finalTarget = "capture"; // var finalTarget = "capture";
#else // #else
var finalTarget = ""; var finalTarget = "";
#end // #end
path.setTarget(finalTarget); path.setTarget(finalTarget);
path.bindTarget(framebuffer, "tex"); path.bindTarget(framebuffer, "tex");
path.drawShader("shader_datas/supersample_resolve/supersample_resolve"); path.drawShader("shader_datas/supersample_resolve/supersample_resolve");
} }
#elseif (rp_rendercapture) // #elseif (rp_rendercapture)
{ // {
path.setTarget("capture"); // path.setTarget("capture");
path.bindTarget(framebuffer, "tex"); // path.bindTarget(framebuffer, "tex");
path.drawShader("shader_datas/copy_pass/copy_pass"); // path.drawShader("shader_datas/copy_pass/copy_pass");
} // }
#end #end
} }
#end #end

View file

@ -1,209 +0,0 @@
package armory.trait.internal;
import iron.Trait;
// import iron.object.Object;
// import iron.object.Transform;
// import iron.system.Input;
// import iron.math.RayCaster;
class SpaceArmory extends Trait {
// var gizmo:Object;
// var arrowX:Object;
// var arrowY:Object;
// var arrowZ:Object;
// var selected:Transform = null;
// var moveX = false;
// var moveY = false;
// var moveZ = false;
// static var first = true;
public function new() {
super();
// notifyOnInit(init);
}
// function init() {
// gizmo = iron.Scene.active.getChild('ArrowGizmo');
// arrowX = iron.Scene.active.getChild('ArrowX');
// arrowY = iron.Scene.active.getChild('ArrowY');
// arrowZ = iron.Scene.active.getChild('ArrowZ');
// notifyOnUpdate(update);
// if (first) {
// first = false;
// #if (kha_krom && arm_render)
// renderCapture();
// #end
// }
// }
// function update() {
// #if arm_viewport
// var keyboard = Input.getKeyboard();
// if (keyboard.started("esc")) {
// var viewStr = iron.Scene.active.camera != null ? '|' + iron.Scene.active.camera.V.toArray() : '';
// trace('__arm|quit' + viewStr);
// }
// #end
// var mouse = Input.getMouse();
// if (mouse.started("right")) {
// var transforms:Array<Transform> = [];
// for (o in iron.Scene.active.meshes) transforms.push(o.transform);
// var hit = RayCaster.closestBoxIntersect(transforms, mouse.x, mouse.y, iron.Scene.active.camera);
// if (hit != null) {
// var loc = hit.loc;
// // gizmo.transform.loc.set(loc.x, loc.y, loc.z);
// // gizmo.transform.buildMatrix();
// selected = hit;
// trace('__arm|select|' + selected.object.name);
// }
// }
// if (selected != null) {
// if (mouse.started()) {
// var transforms = [arrowX.transform, arrowY.transform, arrowZ.transform];
// var hit = RayCaster.closestBoxIntersect(transforms, mouse.x, mouse.y, iron.Scene.active.camera);
// if (hit != null) {
// if (hit.object.name == 'ArrowX') moveX = true;
// else if (hit.object.name == 'ArrowY') moveY = true;
// else if (hit.object.name == 'ArrowX') moveZ = true;
// }
// }
// if (moveX || moveY || moveZ) {
// Input.occupied = true;
// if (moveX) selected.loc.x += mouse.deltaX / 110.0;
// if (moveY) selected.loc.y += mouse.deltaX / 110.0;
// if (moveZ) selected.loc.z += mouse.deltaX / 110.0;
// selected.buildMatrix();
// // gizmo.transform.loc.set(selected.loc.x, selected.loc.y, selected.loc.z);
// // gizmo.transform.buildMatrix();
// }
// }
// if (mouse.released()) {
// Input.occupied = false;
// // Move operator creator into separate class..
// // Map directly to bl operators - setx to translate
// if (moveX) trace('__arm|setx|' + selected.object.name + '|' + selected.loc.x);
// moveX = moveY = moveZ = false;
// }
// #if (js && kha_webgl && !kha_node)
// time += iron.system.Time.delta;
// if (time > 1.0) {
// time = 0;
// reloadOnUpdate();
// }
// #end
// }
// #if (js && kha_webgl && !kha_node)
// static var time = 0.0;
// static var lastMtime:Dynamic = null;
// function reloadOnUpdate() {
// // Reload page on kha.js rewrite
// var khaPath = "kha.js";
// var xhr = new js.html.XMLHttpRequest();
// xhr.open('HEAD', khaPath, true);
// xhr.onreadystatechange = function() {
// if (xhr.readyState == 4 && xhr.status == 200) {
// var mtime = xhr.getResponseHeader('Last-Modified');
// if (lastMtime != null && mtime.toString() != lastMtime) {
// untyped __js__('window.location.reload(true)');
// }
// lastMtime = mtime;
// }
// }
// xhr.send();
// }
// #end
// #if (kha_krom && arm_render)
// static var frame = 0;
// static var captured = false;
// #if arm_render_anim
// static var current = 0.0;
// static var framesCaptured = 0;
// @:access(kha.Scheduler)
// function renderCapture() {
// iron.App.pauseUpdates = true;
// iron.App.notifyOnRender(function(g:kha.graphics4.Graphics) {
// if (captured) return;
// kha.Scheduler.current = current;
// frame++;
// if (frame >= 2) { // Init TAA
// iron.App.pauseUpdates = false;
// if (frame % 2 == 0) { // Alternate TAA
// current += iron.system.Time.delta;
// return;
// }
// var info = iron.Scene.active.raw.capture_info;
// var path = iron.RenderPath.active;
// var tex = path.renderTargets.get("capture").image;
// if (tex != null) {
// var pixels = tex.getPixels();
// var bd = pixels.getData();
// var bo = new haxe.io.BytesOutput();
// var rgb = haxe.io.Bytes.alloc(tex.width * tex.height * 3);
// for (j in 0...tex.height) {
// for (i in 0...tex.width) {
// var k = j * tex.width + i;
// var l = (tex.height - j) * tex.width + i; // Reverse Y
// rgb.set(k * 3 + 0, pixels.get(l * 4 + 2));
// rgb.set(k * 3 + 1, pixels.get(l * 4 + 1));
// rgb.set(k * 3 + 2, pixels.get(l * 4 + 0));
// }
// }
// var pngwriter = new iron.format.png.Writer(bo);
// pngwriter.write(iron.format.png.Tools.buildRGB(tex.width, tex.height, rgb));
// var fname = framesCaptured + "";
// while (fname.length < 4) fname = "0" + fname;
// Krom.fileSaveBytes(info.path + "/" + fname + ".png", bo.getBytes().getData());
// }
// if (framesCaptured++ == info.frame_end) {
// captured = true;
// kha.System.requestShutdown();
// }
// }
// });
// }
// #else
// function renderCapture() {
// iron.App.notifyOnRender(function(g:kha.graphics4.Graphics) {
// if (captured) return;
// frame++;
// if (frame >= 3) {
// var path = iron.RenderPath.active;
// var tex = path.renderTargets.get("capture").image;
// if (tex != null) {
// var pixels = tex.getPixels();
// Krom.fileSaveBytes("render.bin", pixels.getData());
// }
// captured = true;
// kha.System.requestShutdown();
// }
// });
// }
// #end
// #end
}

View file

@ -3,10 +3,10 @@
bl_info = { bl_info = {
"name": "Armory", "name": "Armory",
"category": "Render", "category": "Render",
"location": "Properties -> Render -> Armory Player", "location": "Properties -> Render -> Armory",
"description": "3D Game Engine for Blender", "description": "3D Game Engine for Blender",
"author": "Armory3D.org", "author": "Armory3D.org",
"version": (13, 0, 0), "version": (14, 0, 0),
"blender": (2, 79, 0), "blender": (2, 79, 0),
"wiki_url": "http://armory3d.org/manual", "wiki_url": "http://armory3d.org/manual",
"tracker_url": "https://github.com/armory3d/armory/issues" "tracker_url": "https://github.com/armory3d/armory/issues"
@ -24,8 +24,6 @@ from bpy.types import Operator, AddonPreferences
from bpy.props import * from bpy.props import *
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
with_krom = False
def get_os(): def get_os():
s = platform.system() s = platform.system()
if s == 'Windows': if s == 'Windows':
@ -76,10 +74,6 @@ class ArmoryAddonPreferences(AddonPreferences):
items = [('kodestudio', 'Kode Studio', 'kodestudio'), items = [('kodestudio', 'Kode Studio', 'kodestudio'),
('default', 'System Default', 'default')], ('default', 'System Default', 'default')],
name="Code Editor", default='kodestudio', description='Use this editor for editing scripts') name="Code Editor", default='kodestudio', description='Use this editor for editing scripts')
# kha_version = EnumProperty(
# items = [('bundled', 'Bundled', 'bundled'),
# ('git', 'Git', 'git')],
# name="Kha", default='bundled', description='Select Git if you cloned Kha manually')
ui_scale = FloatProperty(name='UI Scale', description='Adjust UI scale for Armory tools', default=1.0, min=1.0, max=4.0) ui_scale = FloatProperty(name='UI Scale', description='Adjust UI scale for Armory tools', default=1.0, min=1.0, max=4.0)
renderdoc_path = StringProperty(name="RenderDoc Path", description="Binary path", subtype="FILE_PATH", update=renderdoc_path_update, default="") renderdoc_path = StringProperty(name="RenderDoc Path", description="Binary path", subtype="FILE_PATH", update=renderdoc_path_update, default="")
ffmpeg_path = StringProperty(name="FFMPEG Path", description="Binary path", subtype="FILE_PATH", update=ffmpeg_path_update, default="") ffmpeg_path = StringProperty(name="FFMPEG Path", description="Binary path", subtype="FILE_PATH", update=ffmpeg_path_update, default="")
@ -92,11 +86,11 @@ class ArmoryAddonPreferences(AddonPreferences):
skip_update = BoolProperty(name="", default=False) skip_update = BoolProperty(name="", default=False)
def draw(self, context): def draw(self, context):
global with_krom
self.skip_update = False self.skip_update = False
layout = self.layout layout = self.layout
layout.label(text="Welcome to Armory! Click 'Save User Settings' at the bottom to keep Armory enabled.") layout.label(text="Welcome to Armory! Click 'Save User Settings' at the bottom to keep Armory enabled.")
if with_krom: p = bundled_sdk_path()
if os.path.exists(p):
layout.prop(self, "sdk_bundled") layout.prop(self, "sdk_bundled")
if not self.sdk_bundled: if not self.sdk_bundled:
layout.prop(self, "sdk_path") layout.prop(self, "sdk_path")
@ -124,24 +118,27 @@ class ArmoryAddonPreferences(AddonPreferences):
box.prop(self, "save_on_build") box.prop(self, "save_on_build")
box.prop(self, "legacy_shaders") box.prop(self, "legacy_shaders")
def bundled_sdk_path():
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/'
def get_sdk_path(context): def get_sdk_path(context):
global with_krom
user_preferences = context.user_preferences user_preferences = context.user_preferences
addon_prefs = user_preferences.addons["armory"].preferences addon_prefs = user_preferences.addons["armory"].preferences
if with_krom and addon_prefs.sdk_bundled: p = bundled_sdk_path()
if get_os() == 'mac': if os.path.exists(p) and addon_prefs.sdk_bundled:
# SDK on MacOS is located in .app folder due to security return p
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: else:
return addon_prefs.sdk_path return addon_prefs.sdk_path
@ -172,6 +169,159 @@ class ArmAddonStartButton(bpy.types.Operator):
play_in_viewport = False play_in_viewport = False
def execute(self, context): def execute(self, context):
if bpy.app.version >= (2, 80, 1):
from bl_ui import properties_render
# properties_render.RENDER_PT_render.COMPAT_ENGINES.add('ARMORY')
# properties_render.RENDER_PT_output.COMPAT_ENGINES.add('ARMORY')
properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_world
properties_world.WORLD_PT_context_world.COMPAT_ENGINES.add('ARMORY')
properties_world.WORLD_PT_custom_props.COMPAT_ENGINES.add('ARMORY')
properties_world.EEVEE_WORLD_PT_surface.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_material
properties_material.MATERIAL_PT_preview.COMPAT_ENGINES.add('ARMORY')
properties_material.MATERIAL_PT_custom_props.COMPAT_ENGINES.add('ARMORY')
properties_material.EEVEE_MATERIAL_PT_context_material.COMPAT_ENGINES.add('ARMORY')
properties_material.EEVEE_MATERIAL_PT_surface.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_object
properties_object.OBJECT_PT_custom_props.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_particle
properties_particle.PARTICLE_MT_specials.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_MT_hair_dynamics_presets.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_context_particles.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_emission.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_hair_dynamics.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_cache.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_velocity.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_rotation.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_physics.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_boidbrain.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_render.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_draw.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_children.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_field_weights.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_force_fields.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_vertexgroups.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_textures.COMPAT_ENGINES.add('ARMORY')
properties_particle.PARTICLE_PT_custom_props.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_scene
properties_scene.SCENE_PT_scene.COMPAT_ENGINES.add('ARMORY')
properties_scene.SCENE_PT_unit.COMPAT_ENGINES.add('ARMORY')
properties_scene.SCENE_PT_color_management.COMPAT_ENGINES.add('ARMORY')
properties_scene.SCENE_PT_audio.COMPAT_ENGINES.add('ARMORY')
properties_scene.SCENE_PT_physics.COMPAT_ENGINES.add('ARMORY')
properties_scene.SCENE_PT_rigid_body_world.COMPAT_ENGINES.add('ARMORY')
properties_scene.SCENE_PT_rigid_body_cache.COMPAT_ENGINES.add('ARMORY')
properties_scene.SCENE_PT_rigid_body_field_weights.COMPAT_ENGINES.add('ARMORY')
properties_scene.SCENE_PT_custom_props.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_texture
properties_texture.TEXTURE_MT_specials.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_preview.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_context.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_node.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_node_mapping.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_colors.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_clouds.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_wood.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_marble.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_magic.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_blend.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_stucci.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_image.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_image_sampling.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_image_mapping.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_musgrave.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_voronoi.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_distortednoise.COMPAT_ENGINES.add('ARMORY')
properties_texture.TextureSlotPanel.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_mapping.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_influence.COMPAT_ENGINES.add('ARMORY')
properties_texture.TEXTURE_PT_custom_props.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_armature
properties_data_armature.DATA_PT_custom_props_arm.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_bone
properties_data_bone.BONE_PT_custom_props.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_camera
properties_data_camera.CAMERA_MT_presets.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.SAFE_AREAS_MT_presets.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_context_camera.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_lens.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_camera_stereoscopy.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_camera_dof.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_camera_background_image.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_camera_display.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_camera_safe_areas.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_custom_props_camera.COMPAT_ENGINES.add('ARMORY')
properties_data_camera.DATA_PT_custom_props_camera.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_curve
properties_data_curve.DATA_PT_curve_texture_space.COMPAT_ENGINES.add('ARMORY')
properties_data_curve.DATA_PT_custom_props_curve.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_lamp
properties_data_lamp.LAMP_MT_sunsky_presets.COMPAT_ENGINES.add('ARMORY')
properties_data_lamp.DATA_PT_context_lamp.COMPAT_ENGINES.add('ARMORY')
properties_data_lamp.DATA_PT_preview.COMPAT_ENGINES.add('ARMORY')
# properties_data_lamp.DATA_PT_lamp.COMPAT_ENGINES.add('ARMORY')
properties_data_lamp.DATA_PT_EEVEE_lamp.COMPAT_ENGINES.add('ARMORY')
properties_data_lamp.DATA_PT_EEVEE_shadow.COMPAT_ENGINES.add('ARMORY')
properties_data_lamp.DATA_PT_area.COMPAT_ENGINES.add('ARMORY')
properties_data_lamp.DATA_PT_spot.COMPAT_ENGINES.add('ARMORY')
properties_data_lamp.DATA_PT_falloff_curve.COMPAT_ENGINES.add('ARMORY')
properties_data_lamp.DATA_PT_custom_props_lamp.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_lattice
properties_data_lattice.DATA_PT_custom_props_lattice.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_lightprobe
properties_data_lightprobe.DATA_PT_context_lightprobe.COMPAT_ENGINES.add('ARMORY')
properties_data_lightprobe.DATA_PT_lightprobe.COMPAT_ENGINES.add('ARMORY')
properties_data_lightprobe.DATA_PT_lightprobe_parallax.COMPAT_ENGINES.add('ARMORY')
properties_data_lightprobe.DATA_PT_lightprobe_display.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_mesh
properties_data_mesh.MESH_MT_vertex_group_specials.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.MESH_MT_shape_key_specials.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_context_mesh.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_normals.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_texture_space.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_vertex_groups.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_face_maps.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_shape_keys.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_uv_texture.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_vertex_colors.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_customdata.COMPAT_ENGINES.add('ARMORY')
properties_data_mesh.DATA_PT_custom_props_mesh.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_metaball
properties_data_metaball.DATA_PT_mball_texture_space.COMPAT_ENGINES.add('ARMORY')
properties_data_metaball.DATA_PT_custom_props_metaball.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_data_speaker
properties_data_speaker.DATA_PT_context_speaker.COMPAT_ENGINES.add('ARMORY')
properties_data_speaker.DATA_PT_speaker.COMPAT_ENGINES.add('ARMORY')
properties_data_speaker.DATA_PT_distance.COMPAT_ENGINES.add('ARMORY')
properties_data_speaker.DATA_PT_cone.COMPAT_ENGINES.add('ARMORY')
properties_data_speaker.DATA_PT_custom_props_speaker.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_physics_cloth
properties_physics_cloth.PHYSICS_PT_cloth.COMPAT_ENGINES.add('ARMORY')
properties_physics_cloth.PHYSICS_PT_cloth_cache.COMPAT_ENGINES.add('ARMORY')
properties_physics_cloth.PHYSICS_PT_cloth_collision.COMPAT_ENGINES.add('ARMORY')
properties_physics_cloth.PHYSICS_PT_cloth_stiffness.COMPAT_ENGINES.add('ARMORY')
properties_physics_cloth.PHYSICS_PT_cloth_sewing.COMPAT_ENGINES.add('ARMORY')
properties_physics_cloth.PHYSICS_PT_cloth_field_weights.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_physics_common
properties_physics_common.PHYSICS_PT_add.COMPAT_ENGINES.add('ARMORY')
properties_physics_common.PHYSICS_PT_add.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_physics_softbody
properties_physics_softbody.PHYSICS_PT_softbody.COMPAT_ENGINES.add('ARMORY')
properties_physics_softbody.PHYSICS_PT_softbody_cache.COMPAT_ENGINES.add('ARMORY')
properties_physics_softbody.PHYSICS_PT_softbody_goal.COMPAT_ENGINES.add('ARMORY')
properties_physics_softbody.PHYSICS_PT_softbody_edge.COMPAT_ENGINES.add('ARMORY')
properties_physics_softbody.PHYSICS_PT_softbody_collision.COMPAT_ENGINES.add('ARMORY')
properties_physics_softbody.PHYSICS_PT_softbody_solver.COMPAT_ENGINES.add('ARMORY')
properties_physics_softbody.PHYSICS_PT_softbody_field_weights.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_physics_rigidbody
properties_physics_rigidbody.PHYSICS_PT_rigid_body.COMPAT_ENGINES.add('ARMORY')
properties_physics_rigidbody.PHYSICS_PT_rigid_body_collisions.COMPAT_ENGINES.add('ARMORY')
properties_physics_rigidbody.PHYSICS_PT_rigid_body_dynamics.COMPAT_ENGINES.add('ARMORY')
properties_physics_rigidbody.PHYSICS_PT_rigid_body_dynamics.COMPAT_ENGINES.add('ARMORY')
from bl_ui import properties_physics_rigidbody_constraint
properties_physics_rigidbody_constraint.PHYSICS_PT_rigid_body_constraint.COMPAT_ENGINES.add('ARMORY')
sdk_path = get_sdk_path(context) sdk_path = get_sdk_path(context)
if sdk_path == "": if sdk_path == "":
self.report({"ERROR"}, "Configure SDK path first") self.report({"ERROR"}, "Configure SDK path first")
@ -183,7 +333,7 @@ class ArmAddonStartButton(bpy.types.Operator):
start.register() start.register()
ArmAddonStartButton.running = True ArmAddonStartButton.running = True
if not hasattr(bpy.app.handlers, 'scene_update_post'): # 2.8 if not hasattr(bpy.app.handlers, 'scene_update_post'):
bpy.types.VIEW3D_HT_header.remove(draw_view3d_header) bpy.types.VIEW3D_HT_header.remove(draw_view3d_header)
return {"FINISHED"} return {"FINISHED"}
@ -265,14 +415,10 @@ def draw_view3d_header(self, context):
layout.operator("arm_addon.start") layout.operator("arm_addon.start")
def register(): def register():
global with_krom
import importlib.util
if importlib.util.find_spec('barmory') != None:
with_krom = True
bpy.utils.register_module(__name__) bpy.utils.register_module(__name__)
if hasattr(bpy.app.handlers, 'scene_update_post'): if hasattr(bpy.app.handlers, 'scene_update_post'):
bpy.app.handlers.scene_update_post.append(on_scene_update_post) bpy.app.handlers.scene_update_post.append(on_scene_update_post)
else: # 2.8 else:
bpy.types.VIEW3D_HT_header.append(draw_view3d_header) bpy.types.VIEW3D_HT_header.append(draw_view3d_header)
def unregister(): def unregister():

View file

@ -1,78 +0,0 @@
# Translating operators from/to Armory player
# from mathutils import Matrix
# import bpy
# import arm.utils
# import arm.make_state as state
# try:
# import barmory
# except ImportError:
# pass
# def parse_operator(text):
# if text == None:
# return
# cmd = text.split('|')
# # Reflect commands from Armory player in Blender
# if cmd[0] == '__arm':
# if cmd[1] == 'quit':
# bpy.ops.arm.space_stop('EXEC_DEFAULT')
# # Copy view matrix
# if len(cmd) > 2 and bpy.data.worlds['Arm'].arm_play_camera == 'Viewport Shared':
# arstr = cmd[2][1:-1] # Remove []
# ar = arstr.split(',')
# mat = [float(i) for i in ar]
# set_view_mat(mat)
# elif cmd[1] == 'setx':
# bpy.context.scene.objects[cmd[2]].location.x = float(cmd[3])
# elif cmd[1] == 'select':
# if hasattr(bpy.context, 'object') and bpy.context.object != None:
# bpy.context.object.select = False
# bpy.context.scene.objects[cmd[2]].select = True
# bpy.context.scene.objects.active = bpy.context.scene.objects[cmd[2]]
# def send_operator(op):
# # Try to translate operator directly to armory
# if arm.utils.with_krom() and hasattr(bpy.context, 'object') and bpy.context.object != None:
# objname = bpy.context.object.name
# if op.name == 'Translate':
# vec = bpy.context.object.location
# js_source = 'var o = armory.Scene.active.getChild("' + objname + '"); o.transform.loc.set(' + str(vec[0]) + ', ' + str(vec[1]) + ', ' + str(vec[2]) + '); o.transform.dirty = true;'
# barmory.call_js(js_source)
# return True
# elif op.name == 'Resize':
# vec = bpy.context.object.scale
# js_source = 'var o = armory.Scene.active.getChild("' + objname + '"); o.transform.scale.set(' + str(vec[0]) + ', ' + str(vec[1]) + ', ' + str(vec[2]) + '); o.transform.dirty = true;'
# barmory.call_js(js_source)
# return True
# elif op.name == 'Rotate':
# vec = bpy.context.object.rotation_euler.to_quaternion()
# js_source = 'var o = armory.Scene.active.getChild("' + objname + '"); o.transform.rot.set(' + str(vec[1]) + ', ' + str(vec[2]) + ', ' + str(vec[3]) + ' ,' + str(vec[0]) + '); o.transform.dirty = true;'
# barmory.call_js(js_source)
# return True
# return False
# def set_view_mat(mat):
# if state.play_area == None:
# return
# for space in state.play_area.spaces:
# if space.type == 'VIEW_3D':
# m = Matrix()
# m[0][0] = mat[0]
# m[0][1] = mat[1]
# m[0][2] = mat[2]
# m[0][3] = mat[3]
# m[1][0] = mat[4]
# m[1][1] = mat[5]
# m[1][2] = mat[6]
# m[1][3] = mat[7]
# m[2][0] = mat[8]
# m[2][1] = mat[9]
# m[2][2] = mat[10]
# m[2][3] = mat[11]
# m[3][0] = mat[12]
# m[3][1] = mat[13]
# m[3][2] = mat[14]
# m[3][3] = mat[15]
# space.region_3d.view_matrix = m
# break

View file

@ -24,6 +24,7 @@ import arm.log as log
import arm.material.make as make_material import arm.material.make as make_material
import arm.material.mat_batch as mat_batch import arm.material.mat_batch as mat_batch
import arm.make_renderpath as make_renderpath import arm.make_renderpath as make_renderpath
import arm.material.cycles as cycles
NodeTypeNode = 0 NodeTypeNode = 0
NodeTypeBone = 1 NodeTypeBone = 1
@ -687,21 +688,19 @@ class ArmoryExporter:
return None return None
def get_viewport_view_matrix(self): def get_viewport_view_matrix(self):
if self.play_area == None: play_area = self.get_view3d_area()
self.play_area = self.get_view3d_area() if play_area == None:
if self.play_area == None:
return None return None
for space in self.play_area.spaces: for space in play_area.spaces:
if space.type == 'VIEW_3D': if space.type == 'VIEW_3D':
return space.region_3d.view_matrix return space.region_3d.view_matrix
return None return None
def get_viewport_projection_matrix(self): def get_viewport_projection_matrix(self):
if self.play_area == None: play_area = self.get_view3d_area()
self.play_area = self.get_view3d_area() if play_area == None:
if self.play_area == None:
return None, False return None, False
for space in self.play_area.spaces: for space in play_area.spaces:
if space.type == 'VIEW_3D': if space.type == 'VIEW_3D':
# return space.region_3d.perspective_matrix # pesp = window * view # return space.region_3d.perspective_matrix # pesp = window * view
return space.region_3d.window_matrix, space.region_3d.is_perspective return space.region_3d.window_matrix, space.region_3d.is_perspective
@ -1275,16 +1274,16 @@ class ArmoryExporter:
if has_tex: if has_tex:
# Get active uvmap # Get active uvmap
t0map = 0 t0map = 0
uv_textures = exportMesh.uv_textures uv_layers = exportMesh.uv_layers
if uv_textures != None: if uv_layers != None:
if 'UVMap_baked' in uv_textures: if 'UVMap_baked' in uv_layers:
for i in range(0, len(uv_textures)): for i in range(0, len(uv_layers)):
if uv_textures[i].name == 'UVMap_baked': if uv_layers[i].name == 'UVMap_baked':
t0map = i t0map = i
break break
else: else:
for i in range(0, len(uv_textures)): for i in range(0, len(uv_layers)):
if uv_textures[i].active_render: if uv_layers[i].active_render:
t0map = i t0map = i
break break
t1map = 1 if t0map == 0 else 0 t1map = 1 if t0map == 0 else 0
@ -1605,7 +1604,7 @@ class ArmoryExporter:
o['shadowmap_cube'] = True o['shadowmap_cube'] = True
o['shadows_bias'] *= 2.0 o['shadows_bias'] *= 2.0
if bpy.app.version >= (2, 80, 1) and self.scene.render.engine == 'BLENDER_EEVEE': if bpy.app.version >= (2, 80, 1) and (self.scene.render.engine == 'BLENDER_EEVEE' or self.scene.render.engine == 'ARMORY'):
o['color'] = [objref.color[0], objref.color[1], objref.color[2]] o['color'] = [objref.color[0], objref.color[1], objref.color[2]]
o['strength'] = objref.energy o['strength'] = objref.energy
if o['type'] == 'point' or o['type'] == 'spot': if o['type'] == 'point' or o['type'] == 'spot':
@ -1689,10 +1688,8 @@ class ArmoryExporter:
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
if wrd.arm_play_camera != 'Scene': if wrd.arm_play_camera != 'Scene':
pw = self.get_viewport_panels_w() # Tool shelf and properties hidden
proj, is_persp = self.get_viewport_projection_matrix() proj, is_persp = self.get_viewport_projection_matrix()
windowed = not ArmoryExporter.in_viewport if proj != None and is_persp:
if proj != None and is_persp and (pw == 0 or windowed):
self.extract_projection(o, proj, with_planes=False) self.extract_projection(o, proj, with_planes=False)
if objref.type != 'PERSP': if objref.type != 'PERSP':
@ -1764,6 +1761,32 @@ class ArmoryExporter:
o['override_context'] = {} o['override_context'] = {}
o['override_context']['cull_mode'] = 'none' o['override_context']['cull_mode'] = 'none'
def signature_traverse(self, node, sign):
sign += node.type + '-'
if node.type == 'TEX_IMAGE' and node.image != None:
sign += node.image.filepath + '-'
for inp in node.inputs:
if inp.is_linked:
sign = self.signature_traverse(inp.links[0].from_node, sign)
else:
# Unconnected socket
if not hasattr(inp, 'default_value'):
sign += 'o'
elif inp.type == 'RGB' or inp.type == 'RGBA' or inp.type == 'VECTOR':
sign += str(inp.default_value[0])
sign += str(inp.default_value[1])
sign += str(inp.default_value[2])
else:
sign += str(inp.default_value)
return sign
def get_signature(self, mat):
nodes = mat.node_tree.nodes
output_node = cycles.node_by_type(nodes, 'OUTPUT_MATERIAL')
if output_node != None:
sign = self.signature_traverse(output_node, '')
return sign
def export_materials(self): def export_materials(self):
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
@ -1788,6 +1811,12 @@ class ArmoryExporter:
if material == None: if material == None:
continue continue
# Recache material
signature = self.get_signature(material)
if signature != material.signature:
material.is_cached = False
material.signature = signature
o = {} o = {}
o['name'] = arm.utils.asset_name(material) o['name'] = arm.utils.asset_name(material)
@ -1975,12 +2004,11 @@ class ArmoryExporter:
self.output['mesh_datas'] = []; self.output['mesh_datas'] = [];
self.export_mesh(objectRef, scene) self.export_mesh(objectRef, scene)
def execute(self, context, filepath, scene=None, write_capture_info=False, play_area=None): def execute(self, context, filepath, scene=None):
profile_time = time.time() profile_time = time.time()
self.output = {} self.output = {}
self.filepath = filepath self.filepath = filepath
self.play_area = play_area
self.scene = context.scene if scene == None else scene self.scene = context.scene if scene == None else scene
print('Exporting ' + arm.utils.asset_name(self.scene)) print('Exporting ' + arm.utils.asset_name(self.scene))
@ -1989,12 +2017,6 @@ class ArmoryExporter:
self.beginFrame = self.scene.frame_start self.beginFrame = self.scene.frame_start
self.output['frame_time'] = 1.0 / (self.scene.render.fps / self.scene.render.fps_base) self.output['frame_time'] = 1.0 / (self.scene.render.fps / self.scene.render.fps_base)
if write_capture_info:
self.output['capture_info'] = {}
self.output['capture_info']['path'] = bpy.path.abspath(self.scene.render.filepath)
self.output['capture_info']['frame_start'] = int(self.scene.frame_start)
self.output['capture_info']['frame_end'] = int(self.scene.frame_end)
self.bobjectArray = {} self.bobjectArray = {}
self.bobjectBoneArray = {} self.bobjectBoneArray = {}
self.meshArray = {} self.meshArray = {}
@ -2020,7 +2042,11 @@ class ArmoryExporter:
self.preprocess() self.preprocess()
if bpy.app.version >= (2, 80, 1): if bpy.app.version >= (2, 80, 1):
scene_objects = self.scene.collection.all_objects # scene_objects = self.scene.objects
# scene_objects = self.scene.collection.all_objects # crash
scene_objects = []
for lay in self.scene.view_layers:
scene_objects += lay.depsgraph.objects
else: else:
scene_objects = self.scene.objects scene_objects = self.scene.objects
for bobject in scene_objects: for bobject in scene_objects:
@ -2131,18 +2157,6 @@ class ArmoryExporter:
o['near_plane'] = 0.1 o['near_plane'] = 0.1
o['far_plane'] = 100.0 o['far_plane'] = 100.0
o['fov'] = 0.85 o['fov'] = 0.85
# if ArmoryExporter.in_viewport: # Wrong P returned when no camera present?
# pw = self.get_viewport_panels_w()
# proj, is_persp = self.get_viewport_projection_matrix()
# if pw == 0 and is_persp:
# a = proj[0][0]
# b = proj[1][1]
# c = proj[2][2]
# d = proj[2][3]
# k = (c - 1.0) / (c + 1.0)
# o['near_plane'] = (d * (1.0 - k)) / (2.0 * k)
# o['far_plane'] = k * o['near_plane'];
# o['fov'] = 2.0 * math.atan(1.0 / b)
o['type'] = 'perspective' o['type'] = 'perspective'
o['frustum_culling'] = True o['frustum_culling'] = True
o['clear_color'] = self.get_camera_clear_color() o['clear_color'] = self.get_camera_clear_color()
@ -2163,7 +2177,7 @@ class ArmoryExporter:
navigation_trait = {} navigation_trait = {}
navigation_trait['type'] = 'Script' navigation_trait['type'] = 'Script'
navigation_trait['class_name'] = 'armory.trait.WalkNavigation' navigation_trait['class_name'] = 'armory.trait.WalkNavigation'
navigation_trait['parameters'] = [str(arm.utils.get_ease_viewport_camera()).lower()] navigation_trait['parameters'] = ['true'] # ease
o['traits'].append(navigation_trait) o['traits'].append(navigation_trait)
self.output['objects'].append(o) self.output['objects'].append(o)
self.output['camera_ref'] = 'DefaultCamera' self.output['camera_ref'] = 'DefaultCamera'
@ -2304,8 +2318,6 @@ class ArmoryExporter:
ArmoryExporter.export_ui = False ArmoryExporter.export_ui = False
if not hasattr(ArmoryExporter, 'compress_enabled'): if not hasattr(ArmoryExporter, 'compress_enabled'):
ArmoryExporter.compress_enabled = False ArmoryExporter.compress_enabled = False
if not hasattr(ArmoryExporter, 'in_viewport'):
ArmoryExporter.in_viewport = False
if not hasattr(ArmoryExporter, 'import_traits'): if not hasattr(ArmoryExporter, 'import_traits'):
ArmoryExporter.import_traits = [] # Referenced traits ArmoryExporter.import_traits = [] # Referenced traits
ArmoryExporter.option_mesh_only = False ArmoryExporter.option_mesh_only = False
@ -2430,7 +2442,7 @@ class ArmoryExporter:
navigation_trait = {} navigation_trait = {}
navigation_trait['type'] = 'Script' navigation_trait['type'] = 'Script'
navigation_trait['class_name'] = 'armory.trait.WalkNavigation' navigation_trait['class_name'] = 'armory.trait.WalkNavigation'
navigation_trait['parameters'] = [str(arm.utils.get_ease_viewport_camera()).lower()] navigation_trait['parameters'] = ['true'] # ease
o['traits'].append(navigation_trait) o['traits'].append(navigation_trait)
# Map objects to materials, can be used in later stages # Map objects to materials, can be used in later stages

View file

@ -1,176 +1,56 @@
import bpy
import time import time
import os import os
import sys import sys
import bpy
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
import arm.utils import arm.utils
import arm.bridge as bridge
import arm.log as log
import arm.props as props import arm.props as props
import arm.make as make import arm.make as make
import arm.make_state as state import arm.make_state as state
import arm.space_armory as space_armory
import arm.assets as assets
try:
import barmory
except ImportError:
pass
last_time = time.time() last_time = time.time()
last_operator = None last_operator = None
redraw_ui = False
redraw_progress = False
first_update = True first_update = True
v8_started = False
@persistent @persistent
def on_scene_update_post(context): def on_scene_update_pre(context):
# TODO: get rid of this function as soon as there is a proper way to detect object data updates
global last_time global last_time
global last_operator global last_operator
global redraw_ui
global redraw_progress
global first_update global first_update
global v8_started
if first_update == True: # Skip first one, object reports is_update_data if first_update == True: # Skip first one, object reports is_update_data
first_update = False first_update = False
return return
# Redraw at the start of 'next' frame # Redraw player
if redraw_ui and bpy.context.screen != None: with_armory = bpy.context.scene.render.engine == 'ARMORY'
for area in bpy.context.screen.areas: if with_armory:
if area.type == 'VIEW_3D' or area.type == 'PROPERTIES': play_area = None
area.tag_redraw() if bpy.context.screen != None:
redraw_ui = False for area in bpy.context.screen.areas:
if redraw_progress and bpy.context.screen != None: if area.type == 'VIEW_3D':
for area in bpy.context.screen.areas: play_area = area
if area.type == 'INFO': break
area.tag_redraw() if play_area != None and play_area.spaces[0].shading.type == 'MATERIAL':
break if not v8_started:
redraw_progress = False v8_started = True
make.build_viewport()
if time.time() - last_time >= 1 / 60:
last_time = time.time()
play_area.tag_redraw()
else:
v8_started = False
# New operator # Recache edited data
ops = bpy.context.window_manager.operators ops = bpy.context.window_manager.operators
operators_changed = False operators_changed = False
if len(ops) > 0 and last_operator != ops[-1]: if len(ops) > 0 and last_operator != ops[-1]:
last_operator = ops[-1] last_operator = ops[-1]
operators_changed = True operators_changed = True
# Undo was performed - Blender clears the complete operator stack, undo last known operator atleast
# if len(ops) == 0 and last_operator != None:
# if hasattr(bpy.context, 'object'):
# op_changed(last_operator, bpy.context.object)
# last_operator = None
# if state.is_render_anim:
# pass
# elif state.is_render:
# import numpy
# krom_location, krom_path = arm.utils.krom_paths()
# fp = krom_location
# resx, resy = arm.utils.get_render_resolution(arm.utils.get_active_scene())
# wrd = bpy.data.worlds['Arm']
# cformat = wrd.rp_rendercapture_format
# if cformat == '8bit':
# cbits = 4
# ctype = numpy.uint8
# elif cformat == '16bit':
# cbits = 8
# ctype = numpy.float16
# elif cformat == '32bit':
# cbits = 16
# ctype = numpy.float32
# if os.path.isfile(fp + '/render.bin') and os.path.getsize(fp + '/render.bin') == resx * resy * cbits:
# data = numpy.fromfile(fp + '/render.bin', dtype=ctype)
# data = data.astype(float)
# if cformat == '8bit':
# data = numpy.divide(data, 255)
# n = "Render Result"
# if n in bpy.data.images and bpy.data.images[n].size[0] == resx and bpy.data.images[n].size[1] == resy:
# bpy.data.images[n].pixels = data
# else:
# float_buffer = cformat != '8bit'
# image = bpy.data.images.new("Render Result", width=resx, height=resy, float_buffer=float_buffer)
# image.pixels = data
# state.is_render = False
# os.remove(fp + '/render.bin')
# print('Output image captured into Blender - UV/Image Editor - Render Result')
# Player running
state.krom_running = False
if not state.is_paused and bpy.context.screen != None:
for area in bpy.context.screen.areas:
if area.type == 'VIEW_ARMORY':
state.krom_running = True
break
# Auto patch on every operator change
# if not 'Arm' in bpy.data.worlds:
# props.create_wrd()
# wrd = bpy.data.worlds['Arm']
# if state.krom_running and \
# wrd.arm_play_live_patch and \
# wrd.arm_play_auto_build and \
# operators_changed:
# # Otherwise rebuild scene
# if bridge.send_operator(last_operator) == False:
# if state.compileproc == None:
# assets.invalidate_enabled = False
# make.play_project(in_viewport=True)
# assets.invalidate_enabled = True
# Update at 60 fps
fps_mult = 2.0 if (state.krom_running and arm.utils.get_os() == 'win') else 1.0 # Handlers called less frequently on Windows?
fps = 60
if time.time() - last_time >= (1 / (fps * fps_mult)):
last_time = time.time()
if state.krom_running:
# Read krom console
# if barmory.get_console_updated() == 1:
# log.print_player(barmory.get_console())
# Read operator console
# if barmory.get_operator_updated() == 1:
# bridge.parse_operator(barmory.get_operator())
# Tag redraw
if bpy.context.screen != None:
for area in bpy.context.screen.areas:
if area.type == 'VIEW_ARMORY':
area.tag_redraw()
break
# New output has been logged
if log.tag_redraw and bpy.context.screen != None:
log.tag_redraw = False
redraw_progress = True
# Player finished, redraw play buttons
if state.playproc_finished and bpy.context.screen != None:
state.playproc_finished = False
redraw_ui = True
# Compilation finished
if state.compileproc_finished and bpy.context.screen != None:
state.compileproc_finished = False
redraw_ui = True
# Compilation succesfull
if state.compileproc_success:
# Notify embedded player
# if state.krom_running:
# if state.recompiled and wrd.arm_play_live_patch:
# # state.is_paused = False
# barmory.parse_code()
# for s in state.mod_scripts:
# barmory.call_js('armory.Scene.patchTrait("' + s + '");')
# else:
# barmory.call_js('armory.Scene.patch();')
# Or switch to armory space
# elif arm.utils.with_krom() and state.in_viewport:
if arm.utils.with_krom() and state.in_viewport:
state.play_area.type = 'VIEW_ARMORY'
# Prevent immediate operator patch
# if len(ops) > 0:
# last_operator = ops[-1]
# No attribute when using multiple windows?
if hasattr(bpy.context, 'active_object'): if hasattr(bpy.context, 'active_object'):
obj = bpy.context.active_object obj = bpy.context.active_object
if obj != None: if obj != None:
@ -178,7 +58,7 @@ def on_scene_update_post(context):
recache(obj) recache(obj)
if len(ops) > 0 and ops[-1].bl_idname == 'OBJECT_OT_transform_apply': if len(ops) > 0 and ops[-1].bl_idname == 'OBJECT_OT_transform_apply':
recache(obj) recache(obj)
# New children need to be recached # New children
if obj.type == 'ARMATURE': if obj.type == 'ARMATURE':
for c in obj.children: for c in obj.children:
if c.data != None and c.data.is_updated: if c.data != None and c.data.is_updated:
@ -194,7 +74,7 @@ def on_scene_update_post(context):
if operators_changed: if operators_changed:
op_changed(ops[-1], obj) op_changed(ops[-1], obj)
if obj.active_material != None and obj.active_material.is_updated: if obj.active_material != None and obj.active_material.is_updated:
if obj.active_material.lock_cache == True: # is_cached was set to true if obj.active_material.lock_cache == True: # is_cached was set to true, resulting in a is_updated call
obj.active_material.lock_cache = False obj.active_material.lock_cache = False
else: else:
obj.active_material.is_cached = False obj.active_material.is_cached = False
@ -205,6 +85,7 @@ def on_scene_update_post(context):
space.node_tree.is_cached = False space.node_tree.is_cached = False
def recache(obj): def recache(obj):
print('recacheee')
# Moving keyframes triggers is_updated_data.. # Moving keyframes triggers is_updated_data..
if state.compileproc != None: if state.compileproc != None:
return return
@ -282,8 +163,8 @@ def load_library(asset_name):
ref.use_fake_user = True ref.use_fake_user = True
def register(): def register():
if hasattr(bpy.app.handlers, 'scene_update_post'): if hasattr(bpy.app.handlers, 'scene_update_pre'):
bpy.app.handlers.scene_update_post.append(on_scene_update_post) bpy.app.handlers.scene_update_pre.append(on_scene_update_pre)
bpy.app.handlers.save_pre.append(on_save_pre) bpy.app.handlers.save_pre.append(on_save_pre)
bpy.app.handlers.load_post.append(on_load_post) bpy.app.handlers.load_post.append(on_load_post)
# On windows, on_load_post is not called when opening .blend file from explorer # On windows, on_load_post is not called when opening .blend file from explorer
@ -292,7 +173,7 @@ def register():
reload_blend_data() reload_blend_data()
def unregister(): def unregister():
if hasattr(bpy.app.handlers, 'scene_update_post'): if hasattr(bpy.app.handlers, 'scene_update_pre'):
bpy.app.handlers.scene_update_post.remove(on_scene_update_post) bpy.app.handlers.scene_update_pre.remove(on_scene_update_pre)
bpy.app.handlers.save_pre.remove(on_save_pre) bpy.app.handlers.save_pre.remove(on_save_pre)
bpy.app.handlers.load_post.remove(on_load_post) bpy.app.handlers.load_post.remove(on_load_post)

View file

@ -1,4 +1,3 @@
# Key shortcuts
import bpy import bpy
import arm.props_ui as props_ui import arm.props_ui as props_ui
import arm.utils import arm.utils
@ -9,11 +8,6 @@ def register():
wm = bpy.context.window_manager wm = bpy.context.window_manager
km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW") km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW")
km.keymap_items.new(props_ui.ArmoryPlayButton.bl_idname, type='F5', value='PRESS') km.keymap_items.new(props_ui.ArmoryPlayButton.bl_idname, type='F5', value='PRESS')
km.keymap_items.new(props_ui.ArmoryRenderButton.bl_idname, type='F10', value='PRESS')
if arm.utils.with_krom():
km.keymap_items.new(props_ui.ArmoryPlayInViewportButton.bl_idname, type='P', value='PRESS')
else:
km.keymap_items.new(props_ui.ArmoryPlayButton.bl_idname, type='P', value='PRESS')
arm_keymaps.append(km) arm_keymaps.append(km)
def unregister(): def unregister():

View file

@ -1,50 +1,20 @@
import arm.utils
# import arm.bridge as bridge
import arm.make_state as state
progress = 100.0
tag_redraw = False
info_text = '' info_text = ''
# header_info_text = ''
def clear(): def clear():
global info_text global info_text
# global header_info_text
info_text = '' info_text = ''
# if arm.utils.with_krom():
# header_info_text = ''
def format_text(text): def format_text(text):
return (text[:80] + '..') if len(text) > 80 else text # Limit str size return (text[:80] + '..') if len(text) > 80 else text # Limit str size
def krom_trace(text): def krom_trace(text):
# txt = text.split(' ', 1)
# if len(txt) > 1 and txt[1].startswith('__arm'):
# bridge.parse_operator(txt[1])
# else:
print(text) print(text)
def print_info(text): def print_info(text):
global tag_redraw
global info_text global info_text
print(text) print(text)
info_text = format_text(text) info_text = format_text(text)
tag_redraw = True
# def print_player(text):
# global header_info_text
# if state.krom_running:
# header_info_text = format_text(text)
def print_progress(value):
global progress
global tag_redraw
progress = value
tag_redraw = True
def get_progress(self):
global progress
return progress
def warn(text): def warn(text):
print('Armory Warning: ' + text) print('Armory Warning: ' + text)

View file

@ -12,10 +12,10 @@ class GetVelocityNode(Node, ArmLogicTreeNode):
def init(self, context): def init(self, context):
self.inputs.new('ArmNodeSocketObject', 'Object') self.inputs.new('ArmNodeSocketObject', 'Object')
self.outputs.new('NodeSocketVector', 'Linear') self.outputs.new('NodeSocketVector', 'Linear')
# self.outputs.new('NodeSocketVector', 'Linear Factor') //TODO # self.outputs.new('NodeSocketVector', 'Linear Factor') # TODO
# self.outputs[-1].default_value = [1.0, 1.0, 1.0] # self.outputs[-1].default_value = [1.0, 1.0, 1.0]
self.outputs.new('NodeSocketVector', 'Angular') self.outputs.new('NodeSocketVector', 'Angular')
# self.outputs.new('NodeSocketVector', 'Angular Factor')//TODO # self.outputs.new('NodeSocketVector', 'Angular Factor') # TODO
# self.outputs[-1].default_value = [1.0, 1.0, 1.0] # self.outputs[-1].default_value = [1.0, 1.0, 1.0]
add_node(GetVelocityNode, category='Physics') add_node(GetVelocityNode, category='Physics')

View file

@ -20,11 +20,6 @@ import arm.log as log
import arm.lib.make_datas import arm.lib.make_datas
import arm.lib.server import arm.lib.server
from arm.exporter import ArmoryExporter from arm.exporter import ArmoryExporter
import time
try:
import barmory
except ImportError:
pass
exporter = ArmoryExporter() exporter = ArmoryExporter()
scripts_mtime = 0 # Monitor source changes scripts_mtime = 0 # Monitor source changes
@ -58,7 +53,7 @@ def export_data(fp, sdk_path, is_play=False, is_publish=False, in_viewport=False
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
print('\nArmory v{0} ({1})'.format(wrd.arm_version, wrd.arm_commit)) print('\nArmory v{0} ({1})'.format(wrd.arm_version, wrd.arm_commit))
print('OS: ' + arm.utils.get_os() + ', Target: ' + state.target + ', GAPI: ' + arm.utils.get_gapi()) print('OS: ' + arm.utils.get_os() + ', Target: ' + state.target + ', GAPI: ' + arm.utils.get_gapi() + ', Blender: ' + bpy.app.version_string)
# Clean compiled variants if cache is disabled # Clean compiled variants if cache is disabled
build_dir = arm.utils.get_fp_build() build_dir = arm.utils.get_fp_build()
@ -109,12 +104,11 @@ def export_data(fp, sdk_path, is_play=False, is_publish=False, in_viewport=False
navigation_found = False navigation_found = False
ui_found = False ui_found = False
ArmoryExporter.compress_enabled = is_publish and wrd.arm_asset_compression ArmoryExporter.compress_enabled = is_publish and wrd.arm_asset_compression
ArmoryExporter.in_viewport = in_viewport
for scene in bpy.data.scenes: for scene in bpy.data.scenes:
if scene.arm_export: if scene.arm_export:
ext = '.zip' if (scene.arm_compress and is_publish) else '.arm' ext = '.zip' if (scene.arm_compress and is_publish) else '.arm'
asset_path = build_dir + '/compiled/Assets/' + arm.utils.safestr(scene.name) + ext asset_path = build_dir + '/compiled/Assets/' + arm.utils.safestr(scene.name) + ext
exporter.execute(bpy.context, asset_path, scene=scene, write_capture_info=state.is_render_anim, play_area=state.play_area) exporter.execute(bpy.context, asset_path, scene=scene)
if ArmoryExporter.export_physics: if ArmoryExporter.export_physics:
physics_found = True physics_found = True
if ArmoryExporter.export_navigation: if ArmoryExporter.export_navigation:
@ -205,12 +199,8 @@ def export_data(fp, sdk_path, is_play=False, is_publish=False, in_viewport=False
state.last_resy = resy state.last_resy = resy
state.last_scene = scene_name state.last_scene = scene_name
def compile_project(target_name=None, watch=False, patch=False, no_project_file=False): def compile(target_name=None, watch=False, patch=False):
"""
:param no_project_file: Pass '--noproject' to kha make. In the future assets will be copied.
"""
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
fp = arm.utils.get_fp() fp = arm.utils.get_fp()
os.chdir(fp) os.chdir(fp)
@ -234,18 +224,11 @@ def compile_project(target_name=None, watch=False, patch=False, no_project_file=
state.export_gapi = arm.utils.get_gapi() state.export_gapi = arm.utils.get_gapi()
cmd.append('-g') cmd.append('-g')
cmd.append(state.export_gapi) cmd.append(state.export_gapi)
if state.in_viewport:
if arm.utils.glsl_version() >= 330:
cmd.append('--shaderversion')
cmd.append('330')
else:
cmd.append('--shaderversion')
cmd.append('110')
# Kha defaults to 110 on Linux if arm.utils.get_legacy_shaders() and not state.in_viewport:
is_linux = arm.utils.get_os() == 'linux' cmd.append('--shaderversion')
is_native = kha_target_name == 'krom' or kha_target_name == '' cmd.append('110')
if is_linux and is_native and not state.in_viewport and not arm.utils.get_legacy_shaders(): else:
cmd.append('--shaderversion') cmd.append('--shaderversion')
cmd.append('330') cmd.append('330')
@ -271,10 +254,7 @@ def compile_project(target_name=None, watch=False, patch=False, no_project_file=
print("Running: ", cmd) print("Running: ", cmd)
state.compileproc = subprocess.Popen(cmd, stderr=subprocess.PIPE) state.compileproc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
if state.playproc == None: if state.playproc == None:
if state.in_viewport: mode = 'play_viewport' if state.in_viewport else 'play'
mode = 'play_viewport'
else:
mode = 'play'
else: else:
mode = 'build' mode = 'build'
threading.Timer(0.1, watch_patch, [mode]).start() threading.Timer(0.1, watch_patch, [mode]).start()
@ -286,24 +266,38 @@ def compile_project(target_name=None, watch=False, patch=False, no_project_file=
threading.Timer(0.1, watch_compile, [mode]).start() threading.Timer(0.1, watch_compile, [mode]).start()
return state.compileproc return state.compileproc
else: else:
if no_project_file:
cmd.append('--noproject')
print("Running: ", cmd) print("Running: ", cmd)
return subprocess.Popen(cmd) return subprocess.Popen(cmd)
def build_project(is_play=False, is_publish=False, is_render=False, is_render_anim=False, in_viewport=False): def build_viewport():
if state.compileproc != None:
return
if not arm.utils.check_saved(None):
return
if not arm.utils.check_sdkpath(None):
return
if not arm.utils.check_engine(None):
return
arm.utils.check_default_rp()
state.is_export = False
assets.invalidate_enabled = False
play(in_viewport=True)
assets.invalidate_enabled = True
def build(is_play=False, is_publish=False, in_viewport=False):
global profile_time global profile_time
profile_time = time.time() profile_time = time.time()
wrd = bpy.data.worlds['Arm']
state.is_render = is_render
state.is_render_anim = is_render_anim
state.is_publish = is_publish state.is_publish = is_publish
state.in_viewport = in_viewport state.in_viewport = in_viewport
# Save blend # Save blend
if arm.utils.get_save_on_build() and not state.krom_running: if arm.utils.get_save_on_build() and not state.in_viewport:
bpy.ops.wm.save_mainfile() bpy.ops.wm.save_mainfile()
log.clear() log.clear()
@ -325,6 +319,7 @@ def build_project(is_play=False, is_publish=False, is_render=False, is_render_an
os.chdir(fp) os.chdir(fp)
# Create directories # Create directories
wrd = bpy.data.worlds['Arm']
sources_path = 'Sources/' + arm.utils.safestr(wrd.arm_project_package) sources_path = 'Sources/' + arm.utils.safestr(wrd.arm_project_package)
if not os.path.exists(sources_path): if not os.path.exists(sources_path):
os.makedirs(sources_path) os.makedirs(sources_path)
@ -363,9 +358,6 @@ def build_project(is_play=False, is_publish=False, is_render=False, is_render_an
for fn in glob.iglob(os.path.join('include', '**'), recursive=False): for fn in glob.iglob(os.path.join('include', '**'), recursive=False):
shutil.copy(fn, arm.utils.build_dir() + dest + os.path.basename(fn)) shutil.copy(fn, arm.utils.build_dir() + dest + os.path.basename(fn))
if state.playproc == None:
log.print_progress(50)
def stop_project(): def stop_project():
if state.playproc != None: if state.playproc != None:
state.playproc.terminate() state.playproc.terminate()
@ -386,31 +378,24 @@ def watch_play():
else: else:
line += char line += char
state.playproc = None state.playproc = None
state.playproc_finished = True
log.clear() log.clear()
def watch_compile(mode): def watch_compile(mode):
state.compileproc.wait() state.compileproc.wait()
log.print_progress(100)
print('Finished in ' + str(time.time() - profile_time)) print('Finished in ' + str(time.time() - profile_time))
if state.compileproc == None: ## if state.compileproc == None: ##
return return
result = state.compileproc.poll() result = state.compileproc.poll()
state.compileproc = None state.compileproc = None
state.compileproc_finished = True
if result == 0: if result == 0:
bpy.data.worlds['Arm'].arm_recompile = False bpy.data.worlds['Arm'].arm_recompile = False
state.compileproc_success = True
on_compiled(mode) on_compiled(mode)
else: else:
state.compileproc_success = False
log.print_info('Build failed, check console') log.print_info('Build failed, check console')
def watch_patch(mode): def watch_patch(mode):
state.compileproc.wait() state.compileproc.wait()
log.print_progress(100)
state.compileproc = None state.compileproc = None
state.compileproc_finished = True
on_compiled(mode) on_compiled(mode)
def runtime_to_target(in_viewport): def runtime_to_target(in_viewport):
@ -430,21 +415,17 @@ def get_khajs_path(in_viewport, target):
else: # Browser else: # Browser
return arm.utils.build_dir() + '/debug/html5/kha.js' return arm.utils.build_dir() + '/debug/html5/kha.js'
def play_project(in_viewport, is_render=False, is_render_anim=False): def play(in_viewport):
global scripts_mtime global scripts_mtime
global code_parsed global code_parsed
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
log.clear() log.clear()
# Store area
if arm.utils.with_krom() and in_viewport and bpy.context.area != None and bpy.context.area.type == 'VIEW_3D':
state.play_area = bpy.context.area
state.target = runtime_to_target(in_viewport) state.target = runtime_to_target(in_viewport)
# Build data # Build data
build_project(is_play=True, is_render=is_render, is_render_anim=is_render_anim, in_viewport=in_viewport) build(is_play=True, in_viewport=in_viewport)
khajs_path = get_khajs_path(in_viewport, state.target) khajs_path = get_khajs_path(in_viewport, state.target)
if not wrd.arm_cache_compiler or \ if not wrd.arm_cache_compiler or \
@ -484,37 +465,26 @@ def play_project(in_viewport, is_render=False, is_render_anim=False):
# New compile requred - traits changed # New compile requred - traits changed
if wrd.arm_recompile: if wrd.arm_recompile:
state.recompiled = True
if state.krom_running:
# TODO: Unable to live-patch, stop player
bpy.ops.arm.space_stop('EXEC_DEFAULT')
return
if not code_parsed:
code_parsed = True
barmory.parse_code()
else:
code_parsed = False
mode = 'play' mode = 'play'
if state.target == 'native': if state.target == 'native':
state.compileproc = compile_project(target_name='--run') state.compileproc = compile(target_name='--run')
elif state.target == 'krom': elif state.target == 'krom':
if in_viewport: if in_viewport:
mode = 'play_viewport' mode = 'play_viewport'
state.compileproc = compile_project(target_name='krom') state.compileproc = compile(target_name='krom')
else: # Browser else: # Browser
state.compileproc = compile_project(target_name='html5') state.compileproc = compile(target_name='html5')
threading.Timer(0.1, watch_compile, [mode]).start() threading.Timer(0.1, watch_compile, [mode]).start()
else: # kha.js up to date else: # kha.js up to date
state.recompiled = False compile(patch=True)
compile_project(patch=True)
def on_compiled(mode): # build, play, play_viewport, publish def on_compiled(mode): # build, play, play_viewport, publish
log.clear() log.clear()
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
# Launch project in new window if mode == 'play_viewport':
if mode == 'play': open(arm.utils.get_fp_build() + '/krom/krom.lock', 'w').close()
elif mode == 'play':
if wrd.arm_play_runtime == 'Browser': if wrd.arm_play_runtime == 'Browser':
# Start server # Start server
os.chdir(arm.utils.get_fp()) os.chdir(arm.utils.get_fp())
@ -531,8 +501,6 @@ def on_compiled(mode): # build, play, play_viewport, publish
if arm.utils.get_os() == 'mac': # TODO: Krom sound freezes on MacOS if arm.utils.get_os() == 'mac': # TODO: Krom sound freezes on MacOS
args.append('--nosound') args.append('--nosound')
if state.is_render:
args.append('--nowindow')
args.append('--stdout') args.append('--stdout')
args.append(arm.utils.get_fp_build() + '/krom.txt') args.append(arm.utils.get_fp_build() + '/krom.txt')
state.playproc = subprocess.Popen(args, stderr=subprocess.PIPE) state.playproc = subprocess.Popen(args, stderr=subprocess.PIPE)
@ -610,7 +578,7 @@ def on_compiled(mode): # build, play, play_viewport, publish
else: else:
print('Exported makefiles to ' + files_path + '-build') print('Exported makefiles to ' + files_path + '-build')
def clean_project(): def clean():
os.chdir(arm.utils.get_fp()) os.chdir(arm.utils.get_fp())
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
@ -646,11 +614,3 @@ def clean_project():
mat.is_cached = False mat.is_cached = False
print('Project cleaned') print('Project cleaned')
def get_render_result():
play_project(False, is_render=True)
def get_render_anim_result():
if bpy.context.scene != None:
print('Capturing animation frames into ' + bpy.context.scene.render.filepath)
play_project(False, is_render=True, is_render_anim=True)

View file

@ -279,11 +279,6 @@ def build():
assets.add_shader_pass('deferred_indirect') assets.add_shader_pass('deferred_indirect')
assets.add_shader_pass('deferred_light') assets.add_shader_pass('deferred_light')
assets.add_shader_pass('deferred_light_quad') assets.add_shader_pass('deferred_light_quad')
if rpdat.rp_rendercapture:
assets.add_khafile_def('rp_rendercapture')
assets.add_khafile_def('rp_rendercapture_format={0}'.format(wrd.rp_rendercapture_format))
assets.add_shader_pass('copy_pass')
if rpdat.rp_volumetriclight: if rpdat.rp_volumetriclight:
assets.add_khafile_def('rp_volumetriclight') assets.add_khafile_def('rp_volumetriclight')

View file

@ -1,8 +1,6 @@
target = 'krom' target = 'krom'
last_target = 'krom' last_target = 'krom'
in_viewport = False
is_export = False
export_gapi = '' export_gapi = ''
last_in_viewport = False last_in_viewport = False
last_resx = 0 last_resx = 0
@ -13,13 +11,6 @@ last_scene = ''
last_world_defs = '' last_world_defs = ''
playproc = None playproc = None
compileproc = None compileproc = None
playproc_finished = False
compileproc_finished = False
compileproc_success = False
play_area = None
krom_running = False
is_paused = False
is_render = False
is_render_anim = False
recompiled = False
mod_scripts = [] mod_scripts = []
in_viewport = False
is_export = False

View file

@ -28,8 +28,6 @@ def get_signature(mat):
sign += '1' if mat.arm_cast_shadow else '0' sign += '1' if mat.arm_cast_shadow else '0'
sign += '1' if mat.arm_overlay else '0' sign += '1' if mat.arm_overlay else '0'
sign += '1' if mat.arm_cull_mode == 'Clockwise' else '0' sign += '1' if mat.arm_cull_mode == 'Clockwise' else '0'
sign += '1' if mat.arm_tess else '0'
sign += '1' if mat.arm_tess_shadows else '0'
return sign return sign
def traverse_tree2(node, ar): def traverse_tree2(node, ar):

View file

@ -9,10 +9,6 @@ import arm.utils
import arm.make import arm.make
import arm.props_renderpath as props_renderpath import arm.props_renderpath as props_renderpath
import arm.proxy import arm.proxy
try:
import barmory
except ImportError:
pass
# Armory version # Armory version
arm_version = '0.4' arm_version = '0.4'
@ -78,7 +74,6 @@ def proxy_sync_traits(self, context):
def init_properties(): def init_properties():
global arm_version global arm_version
bpy.types.World.arm_recompile = BoolProperty(name="Recompile", description="Recompile sources on next play", default=True) bpy.types.World.arm_recompile = BoolProperty(name="Recompile", description="Recompile sources on next play", default=True)
bpy.types.World.arm_progress = FloatProperty(name="Building", description="Current build progress", default=100.0, min=0.0, max=100.0, soft_min=0.0, soft_max=100.0, subtype='PERCENTAGE', get=log.get_progress)
bpy.types.World.arm_version = StringProperty(name="Version", description="Armory SDK version", default="") bpy.types.World.arm_version = StringProperty(name="Version", description="Armory SDK version", default="")
bpy.types.World.arm_commit = StringProperty(name="Version Commit", description="Armory SDK version", default="") bpy.types.World.arm_commit = StringProperty(name="Version Commit", description="Armory SDK version", default="")
bpy.types.World.arm_project_name = StringProperty(name="Name", description="Exported project name", default="", update=invalidate_compiler_cache) bpy.types.World.arm_project_name = StringProperty(name="Name", description="Exported project name", default="", update=invalidate_compiler_cache)
@ -129,8 +124,6 @@ def init_properties():
bpy.types.World.arm_cache_shaders = BoolProperty(name="Cache Shaders", description="Do not rebuild existing shaders", default=True) bpy.types.World.arm_cache_shaders = BoolProperty(name="Cache Shaders", description="Do not rebuild existing shaders", default=True)
bpy.types.World.arm_cache_compiler = BoolProperty(name="Cache Compiler", description="Only recompile sources when required", default=True) bpy.types.World.arm_cache_compiler = BoolProperty(name="Cache Compiler", description="Only recompile sources when required", default=True)
bpy.types.World.arm_gpu_processing = BoolProperty(name="GPU Processing", description="Utilize GPU for asset pre-processing at build time", default=True, update=assets.invalidate_compiled_data) bpy.types.World.arm_gpu_processing = BoolProperty(name="GPU Processing", description="Utilize GPU for asset pre-processing at build time", default=True, update=assets.invalidate_compiled_data)
# bpy.types.World.arm_play_live_patch = BoolProperty(name="Live Patch", description="Sync running player data to Blender", default=True)
# bpy.types.World.arm_play_auto_build = BoolProperty(name="Auto Build", description="Rebuild scene on operator changes", default=True)
bpy.types.World.arm_play_camera = EnumProperty( bpy.types.World.arm_play_camera = EnumProperty(
items=[('Scene', 'Scene', 'Scene'), items=[('Scene', 'Scene', 'Scene'),
('Viewport', 'Viewport', 'Viewport'), ('Viewport', 'Viewport', 'Viewport'),
@ -198,8 +191,6 @@ def init_properties():
bpy.types.Speaker.arm_stream = BoolProperty(name="Stream", description="Stream this sound", default=False) bpy.types.Speaker.arm_stream = BoolProperty(name="Stream", description="Stream this sound", default=False)
# For mesh # For mesh
bpy.types.Mesh.arm_cached = BoolProperty(name="Mesh Cached", description="No need to reexport mesh data", default=False) bpy.types.Mesh.arm_cached = BoolProperty(name="Mesh Cached", description="No need to reexport mesh data", default=False)
# bpy.types.Mesh.arm_cached_verts = IntProperty(name="Last Verts", description="Number of vertices in last export", default=0)
# bpy.types.Mesh.arm_cached_edges = IntProperty(name="Last Edges", description="Number of edges in last export", default=0)
bpy.types.Mesh.arm_aabb = FloatVectorProperty(name="AABB", size=3, default=[0,0,0]) bpy.types.Mesh.arm_aabb = FloatVectorProperty(name="AABB", size=3, default=[0,0,0])
bpy.types.Mesh.arm_dynamic_usage = BoolProperty(name="Dynamic Usage", description="Mesh data can change at runtime", default=False) bpy.types.Mesh.arm_dynamic_usage = BoolProperty(name="Dynamic Usage", description="Mesh data can change at runtime", default=False)
bpy.types.Mesh.arm_compress = BoolProperty(name="Compress", description="Pack data into zip file", default=False) bpy.types.Mesh.arm_compress = BoolProperty(name="Compress", description="Pack data into zip file", default=False)
@ -243,12 +234,6 @@ def init_properties():
bpy.types.World.arm_envtex_sun_direction = FloatVectorProperty(name="Sun Direction", size=3, default=[0,0,0]) bpy.types.World.arm_envtex_sun_direction = FloatVectorProperty(name="Sun Direction", size=3, default=[0,0,0])
bpy.types.World.arm_envtex_turbidity = FloatProperty(name="Turbidity", default=1.0) bpy.types.World.arm_envtex_turbidity = FloatProperty(name="Turbidity", default=1.0)
bpy.types.World.arm_envtex_ground_albedo = FloatProperty(name="Ground Albedo", default=0.0) bpy.types.World.arm_envtex_ground_albedo = FloatProperty(name="Ground Albedo", default=0.0)
bpy.types.World.rp_rendercapture_format = EnumProperty(
items=[('8bit', '8bit', '8bit'),
('16bit', '16bit', '16bit'),
('32bit', '32bit', '32bit')],
name="Capture Format", description="Bits per color channel", default='8bit', update=props_renderpath.update_renderpath)
# For material
bpy.types.Material.arm_cast_shadow = BoolProperty(name="Cast Shadow", default=True) bpy.types.Material.arm_cast_shadow = BoolProperty(name="Cast Shadow", default=True)
bpy.types.Material.arm_receive_shadow = BoolProperty(name="Receive Shadow", default=True) bpy.types.Material.arm_receive_shadow = BoolProperty(name="Receive Shadow", default=True)
bpy.types.Material.arm_overlay = BoolProperty(name="Overlay", default=False) bpy.types.Material.arm_overlay = BoolProperty(name="Overlay", default=False)
@ -338,10 +323,7 @@ def init_properties_on_load():
print('Project updated to sdk v' + arm_version) print('Project updated to sdk v' + arm_version)
wrd.arm_version = arm_version wrd.arm_version = arm_version
wrd.arm_commit = arm_commit wrd.arm_commit = arm_commit
arm.make.clean_project() arm.make.clean()
# Set url for embedded player
if arm.utils.with_krom():
barmory.set_files_location(arm.utils.get_fp_build() + '/krom')
def register(): def register():
init_properties() init_properties()

View file

@ -36,7 +36,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False rpdat.rp_dfgi = False
rpdat.rp_bloom = False rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off' rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display' rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Linear' rpdat.arm_texture_filter = 'Linear'
@ -69,7 +68,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False rpdat.rp_dfgi = False
rpdat.rp_bloom = False rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off' rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display' rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Anisotropic' rpdat.arm_texture_filter = 'Anisotropic'
@ -101,7 +99,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False rpdat.rp_dfgi = False
rpdat.rp_bloom = False rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off' rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display' rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Anisotropic' rpdat.arm_texture_filter = 'Anisotropic'
@ -135,7 +132,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False rpdat.rp_dfgi = False
rpdat.rp_bloom = True rpdat.rp_bloom = True
rpdat.rp_eyeadapt = False rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = True
rpdat.rp_motionblur = 'Off' rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display' rpdat.arm_rp_resolution = 'Display'
rpdat.arm_material_model = 'Full' rpdat.arm_material_model = 'Full'
@ -169,7 +165,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False rpdat.rp_dfgi = False
rpdat.rp_bloom = False rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off' rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display' rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Point' rpdat.arm_texture_filter = 'Point'
@ -202,7 +197,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False rpdat.rp_dfgi = False
rpdat.rp_bloom = False rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off' rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display' rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Linear' rpdat.arm_texture_filter = 'Linear'
@ -238,7 +232,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False rpdat.rp_dfgi = False
rpdat.rp_bloom = True rpdat.rp_bloom = True
rpdat.rp_eyeadapt = False rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off' rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display' rpdat.arm_rp_resolution = 'Display'
rpdat.arm_material_model = 'Full' rpdat.arm_material_model = 'Full'
@ -272,7 +265,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False rpdat.rp_dfgi = False
rpdat.rp_bloom = False rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off' rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display' rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Linear' rpdat.arm_texture_filter = 'Linear'
@ -404,7 +396,6 @@ class ArmRPListItem(bpy.types.PropertyGroup):
rp_dfgi = BoolProperty(name="DFGI", description="Distance field global illumination", default=False) rp_dfgi = BoolProperty(name="DFGI", description="Distance field global illumination", default=False)
rp_bloom = BoolProperty(name="Bloom", description="Bloom processing", default=False, update=update_renderpath) rp_bloom = BoolProperty(name="Bloom", description="Bloom processing", default=False, update=update_renderpath)
rp_eyeadapt = BoolProperty(name="Eye Adaptation", description="Auto-exposure based on histogram", default=False, update=update_renderpath) rp_eyeadapt = BoolProperty(name="Eye Adaptation", description="Auto-exposure based on histogram", default=False, update=update_renderpath)
rp_rendercapture = BoolProperty(name="Render Capture", description="Save output as render result", default=False, update=update_renderpath)
rp_motionblur = EnumProperty( rp_motionblur = EnumProperty(
items=[('Off', 'Off', 'Off'), items=[('Off', 'Off', 'Off'),
('Camera', 'Camera', 'Camera'), ('Camera', 'Camera', 'Camera'),

View file

@ -202,6 +202,7 @@ class InvalidateMaterialCacheButton(bpy.types.Operator):
def execute(self, context): def execute(self, context):
context.material.is_cached = False context.material.is_cached = False
context.material.signature = ''
return{'FINISHED'} return{'FINISHED'}
class InvalidateGPCacheButton(bpy.types.Operator): class InvalidateGPCacheButton(bpy.types.Operator):
@ -289,34 +290,13 @@ class ArmoryPlayerPanel(bpy.types.Panel):
row.operator("arm.play", icon="PLAY") row.operator("arm.play", icon="PLAY")
else: else:
row.operator("arm.stop", icon="MESH_PLANE") row.operator("arm.stop", icon="MESH_PLANE")
if state.playproc == None and state.krom_running == False: row.operator("arm.build")
row.operator("arm.build")
else:
row.operator("arm.patch")
row.operator("arm.clean_menu") row.operator("arm.clean_menu")
row = layout.row() row = layout.row()
row.prop(wrd, 'arm_play_runtime', text="") row.prop(wrd, 'arm_play_runtime', text="")
row.prop(wrd, 'arm_play_camera', text="") row.prop(wrd, 'arm_play_camera', text="")
class ArmoryRenderPanel(bpy.types.Panel):
bl_label = "Armory Render"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.operator("arm.render", icon="RENDER_STILL")
row.operator("arm.render_anim", icon="RENDER_ANIMATION")
col = layout.column()
col.prop(bpy.data.worlds['Arm'], "rp_rendercapture_format")
if bpy.context.scene != None:
col.prop(bpy.context.scene.render, "filepath")
class ArmoryExporterPanel(bpy.types.Panel): class ArmoryExporterPanel(bpy.types.Panel):
bl_label = "Armory Exporter" bl_label = "Armory Exporter"
bl_space_type = "PROPERTIES" bl_space_type = "PROPERTIES"
@ -330,7 +310,7 @@ class ArmoryExporterPanel(bpy.types.Panel):
row = layout.row(align=True) row = layout.row(align=True)
row.alignment = 'EXPAND' row.alignment = 'EXPAND'
row.operator("arm.build_project") row.operator("arm.build_project")
row.operator("arm.patch_project") # row.operator("arm.patch_project")
row.operator("arm.publish_project", icon="EXPORT") row.operator("arm.publish_project", icon="EXPORT")
row.enabled = wrd.arm_exporterlist_index >= 0 and len(wrd.arm_exporterlist) > 0 row.enabled = wrd.arm_exporterlist_index >= 0 and len(wrd.arm_exporterlist) > 0
@ -385,11 +365,6 @@ class ArmoryProjectPanel(bpy.types.Panel):
col.prop(wrd, 'arm_play_console') col.prop(wrd, 'arm_play_console')
col.prop(wrd, 'arm_dce') col.prop(wrd, 'arm_dce')
col.prop(wrd, 'arm_minify_js') col.prop(wrd, 'arm_minify_js')
# if arm.utils.with_krom():
# col.prop(wrd, 'arm_play_live_patch')
# colb = col.column()
# colb.enabled = wrd.arm_play_live_patch
# colb.prop(wrd, 'arm_play_auto_build')
col = row.column() col = row.column()
col.prop(wrd, 'arm_cache_shaders') col.prop(wrd, 'arm_cache_shaders')
col.prop(wrd, 'arm_cache_compiler') col.prop(wrd, 'arm_cache_compiler')
@ -515,57 +490,9 @@ class ArmoryPlayButton(bpy.types.Operator):
arm.utils.check_default_rp() arm.utils.check_default_rp()
rpdat = arm.utils.get_rp()
if rpdat.rp_rendercapture == True:
rpdat.rp_rendercapture = False
state.is_export = False state.is_export = False
assets.invalidate_enabled = False assets.invalidate_enabled = False
make.play_project(False) make.play(in_viewport=False)
assets.invalidate_enabled = True
return{'FINISHED'}
class ArmoryPlayInViewportButton(bpy.types.Operator):
'''Launch player in 3D viewport'''
bl_idname = 'arm.play_in_viewport'
bl_label = 'Play in Viewport'
def execute(self, context):
if state.compileproc != None:
return {"CANCELLED"}
if not arm.utils.check_saved(self):
return {"CANCELLED"}
if not arm.utils.check_sdkpath(self):
return {"CANCELLED"}
if not arm.utils.check_engine(self):
return {"CANCELLED"}
if context.area == None:
return {"CANCELLED"}
arm.utils.check_default_rp()
rpdat = arm.utils.get_rp()
if rpdat.rp_rendercapture == True:
rpdat.rp_rendercapture = False
state.is_export = False
assets.invalidate_enabled = False
if state.playproc == None and state.krom_running == False:
if context.area.type != 'VIEW_3D':
return {"CANCELLED"}
# Cancel viewport render
for space in context.area.spaces:
if space.type == 'VIEW_3D':
if space.viewport_shade == 'RENDERED':
space.viewport_shade = 'SOLID'
break
make.play_project(True)
else:
make.play_project(True)
assets.invalidate_enabled = True assets.invalidate_enabled = True
return{'FINISHED'} return{'FINISHED'}
@ -598,8 +525,8 @@ class ArmoryBuildButton(bpy.types.Operator):
state.target = make.runtime_to_target(in_viewport=False) state.target = make.runtime_to_target(in_viewport=False)
state.is_export = False state.is_export = False
assets.invalidate_enabled = False assets.invalidate_enabled = False
make.build_project() make.build()
make.compile_project(watch=True) make.compile(watch=True)
assets.invalidate_enabled = True assets.invalidate_enabled = True
return{'FINISHED'} return{'FINISHED'}
@ -636,53 +563,8 @@ class ArmoryBuildProjectButton(bpy.types.Operator):
state.is_export = True state.is_export = True
assets.invalidate_shader_cache(None, None) assets.invalidate_shader_cache(None, None)
assets.invalidate_enabled = False assets.invalidate_enabled = False
make.build_project() make.build()
make.compile_project(watch=True) make.compile(watch=True)
state.is_export = False
wrd.arm_rplist_index = rplist_index
assets.invalidate_enabled = True
return{'FINISHED'}
class ArmoryPatchProjectButton(bpy.types.Operator):
'''
Build/compile project without generating project files.
This allows iterating faster on native platforms since project file is not reloaded.
'''
bl_idname = 'arm.patch_project'
bl_label = 'Patch'
def execute(self, context):
if not arm.utils.check_saved(self):
return {"CANCELLED"}
if not arm.utils.check_sdkpath(self):
return {"CANCELLED"}
if not arm.utils.check_engine(self):
return {"CANCELLED"}
self.report({'INFO'}, 'Patching project, check console for details.')
arm.utils.check_projectpath(self)
arm.utils.check_default_rp()
wrd = bpy.data.worlds['Arm']
item = wrd.arm_exporterlist[wrd.arm_exporterlist_index]
if item.arm_project_rp == '':
item.arm_project_rp = wrd.arm_rplist[wrd.arm_rplist_index].name
# Assume unique rp names
rplist_index = wrd.arm_rplist_index
for i in range(0, len(wrd.arm_rplist)):
if wrd.arm_rplist[i].name == item.arm_project_rp:
wrd.arm_rplist_index = i
break
#make.clean_project()
state.target = item.arm_project_target
state.is_export = True
assets.invalidate_enabled = False
make.build_project(is_publish=True)
make.compile_project(no_project_file=True)
state.is_export = False state.is_export = False
wrd.arm_rplist_index = rplist_index wrd.arm_rplist_index = rplist_index
assets.invalidate_enabled = True assets.invalidate_enabled = True
@ -720,28 +602,17 @@ class ArmoryPublishProjectButton(bpy.types.Operator):
wrd.arm_rplist_index = i wrd.arm_rplist_index = i
break break
make.clean_project() make.clean()
state.target = item.arm_project_target state.target = item.arm_project_target
state.is_export = True state.is_export = True
assets.invalidate_enabled = False assets.invalidate_enabled = False
make.build_project(is_publish=True) make.build(is_publish=True)
make.compile_project(watch=True) make.compile(watch=True)
state.is_export = False state.is_export = False
wrd.arm_rplist_index = rplist_index wrd.arm_rplist_index = rplist_index
assets.invalidate_enabled = True assets.invalidate_enabled = True
return{'FINISHED'} return{'FINISHED'}
class ArmoryPatchButton(bpy.types.Operator):
'''Update currently running player instance'''
bl_idname = 'arm.patch'
bl_label = 'Patch'
def execute(self, context):
assets.invalidate_enabled = False
make.play_project(True)
assets.invalidate_enabled = True
return{'FINISHED'}
class ArmoryOpenProjectFolderButton(bpy.types.Operator): class ArmoryOpenProjectFolderButton(bpy.types.Operator):
'''Open project folder''' '''Open project folder'''
bl_idname = 'arm.open_project_folder' bl_idname = 'arm.open_project_folder'
@ -793,92 +664,14 @@ class ArmoryCleanProjectButton(bpy.types.Operator):
if not arm.utils.check_saved(self): if not arm.utils.check_saved(self):
return {"CANCELLED"} return {"CANCELLED"}
make.clean_project() make.clean()
return{'FINISHED'} return{'FINISHED'}
class ArmoryRenderButton(bpy.types.Operator):
'''Capture Armory output as render result'''
bl_idname = 'arm.render'
bl_label = 'Render'
def execute(self, context):
if not arm.utils.check_saved(self):
return {"CANCELLED"}
if not arm.utils.check_sdkpath(self):
return {"CANCELLED"}
if not arm.utils.check_engine(self):
return {"CANCELLED"}
arm.utils.check_default_rp()
if state.playproc != None:
make.stop_project()
if bpy.data.worlds['Arm'].arm_play_runtime != 'Krom':
bpy.data.worlds['Arm'].arm_play_runtime = 'Krom'
rpdat = arm.utils.get_rp()
if rpdat.rp_rendercapture == False:
rpdat.rp_rendercapture = True
if rpdat.rp_antialiasing != 'TAA':
rpdat.rp_antialiasing = 'TAA'
assets.invalidate_enabled = False
make.get_render_result()
assets.invalidate_enabled = True
return{'FINISHED'}
class ArmoryRenderAnimButton(bpy.types.Operator):
'''Capture Armory output as render result'''
bl_idname = 'arm.render_anim'
bl_label = 'Animation'
def execute(self, context):
if not arm.utils.check_saved(self):
return {"CANCELLED"}
if not arm.utils.check_sdkpath(self):
return {"CANCELLED"}
if not arm.utils.check_engine(self):
return {"CANCELLED"}
arm.utils.check_default_rp()
if state.playproc != None:
make.stop_project()
if bpy.data.worlds['Arm'].arm_play_runtime != 'Krom':
bpy.data.worlds['Arm'].arm_play_runtime = 'Krom'
rpdat = arm.utils.get_rp()
if rpdat.rp_rendercapture == False:
rpdat.rp_rendercapture = True
if rpdat.rp_antialiasing != 'TAA':
rpdat.rp_antialiasing = 'TAA'
assets.invalidate_enabled = False
make.get_render_anim_result()
assets.invalidate_enabled = True
return{'FINISHED'}
# Play button in 3D View panel
def draw_view3d_header(self, context): def draw_view3d_header(self, context):
layout = self.layout if state.compileproc != None:
if state.playproc == None and state.compileproc == None: self.layout.label('Compiling..')
if arm.utils.with_krom(): elif log.info_text != '':
layout.operator("arm.play_in_viewport", icon="PLAY") self.layout.label(log.info_text)
else:
layout.operator("arm.play", icon="PLAY")
else:
layout.operator("arm.stop", icon="MESH_PLANE")
# Info panel in header
def draw_info_header(self, context):
layout = self.layout
if 'Arm' not in bpy.data.worlds:
return
wrd = bpy.data.worlds['Arm']
if wrd.arm_progress < 100:
layout.prop(wrd, 'arm_progress')
if log.info_text != '':
layout.label(log.info_text)
class ArmRenderPathPanel(bpy.types.Panel): class ArmRenderPathPanel(bpy.types.Panel):
bl_label = "Armory Render Path" bl_label = "Armory Render Path"
@ -1486,27 +1279,21 @@ def register():
bpy.utils.register_class(InvalidateGPCacheButton) bpy.utils.register_class(InvalidateGPCacheButton)
bpy.utils.register_class(MaterialPropsPanel) bpy.utils.register_class(MaterialPropsPanel)
bpy.utils.register_class(ArmoryPlayerPanel) bpy.utils.register_class(ArmoryPlayerPanel)
bpy.utils.register_class(ArmoryRenderPanel)
bpy.utils.register_class(ArmoryExporterPanel) bpy.utils.register_class(ArmoryExporterPanel)
bpy.utils.register_class(ArmoryProjectPanel) bpy.utils.register_class(ArmoryProjectPanel)
bpy.utils.register_class(ArmRenderPathPanel) bpy.utils.register_class(ArmRenderPathPanel)
bpy.utils.register_class(ArmBakePanel) bpy.utils.register_class(ArmBakePanel)
# bpy.utils.register_class(ArmVirtualInputPanel) # bpy.utils.register_class(ArmVirtualInputPanel)
bpy.utils.register_class(ArmoryPlayButton) bpy.utils.register_class(ArmoryPlayButton)
bpy.utils.register_class(ArmoryPlayInViewportButton)
bpy.utils.register_class(ArmoryStopButton) bpy.utils.register_class(ArmoryStopButton)
bpy.utils.register_class(ArmoryBuildButton) bpy.utils.register_class(ArmoryBuildButton)
bpy.utils.register_class(ArmoryBuildProjectButton) bpy.utils.register_class(ArmoryBuildProjectButton)
bpy.utils.register_class(ArmoryPatchProjectButton)
bpy.utils.register_class(ArmoryPatchButton)
bpy.utils.register_class(ArmoryOpenProjectFolderButton) bpy.utils.register_class(ArmoryOpenProjectFolderButton)
bpy.utils.register_class(ArmoryKodeStudioButton) bpy.utils.register_class(ArmoryKodeStudioButton)
bpy.utils.register_class(CleanMenu) bpy.utils.register_class(CleanMenu)
bpy.utils.register_class(CleanButtonMenu) bpy.utils.register_class(CleanButtonMenu)
bpy.utils.register_class(ArmoryCleanProjectButton) bpy.utils.register_class(ArmoryCleanProjectButton)
bpy.utils.register_class(ArmoryPublishProjectButton) bpy.utils.register_class(ArmoryPublishProjectButton)
bpy.utils.register_class(ArmoryRenderButton)
bpy.utils.register_class(ArmoryRenderAnimButton)
bpy.utils.register_class(ArmoryGenerateNavmeshButton) bpy.utils.register_class(ArmoryGenerateNavmeshButton)
bpy.utils.register_class(ArmNavigationPanel) bpy.utils.register_class(ArmNavigationPanel)
bpy.utils.register_class(ArmGenLodButton) bpy.utils.register_class(ArmGenLodButton)
@ -1518,14 +1305,10 @@ def register():
bpy.utils.register_class(ArmProxyApplyAllButton) bpy.utils.register_class(ArmProxyApplyAllButton)
bpy.utils.register_class(ArmSyncProxyButton) bpy.utils.register_class(ArmSyncProxyButton)
bpy.utils.register_class(ArmPrintTraitsButton) bpy.utils.register_class(ArmPrintTraitsButton)
bpy.types.VIEW3D_HT_header.append(draw_view3d_header) bpy.types.VIEW3D_HT_header.append(draw_view3d_header)
bpy.types.INFO_HT_header.append(draw_info_header)
def unregister(): def unregister():
bpy.types.VIEW3D_HT_header.remove(draw_view3d_header) bpy.types.VIEW3D_HT_header.remove(draw_view3d_header)
bpy.types.INFO_HT_header.remove(draw_info_header)
bpy.utils.unregister_class(ObjectPropsPanel) bpy.utils.unregister_class(ObjectPropsPanel)
bpy.utils.unregister_class(ModifiersPropsPanel) bpy.utils.unregister_class(ModifiersPropsPanel)
bpy.utils.unregister_class(ParticlesPropsPanel) bpy.utils.unregister_class(ParticlesPropsPanel)
@ -1537,27 +1320,21 @@ def unregister():
bpy.utils.unregister_class(InvalidateGPCacheButton) bpy.utils.unregister_class(InvalidateGPCacheButton)
bpy.utils.unregister_class(MaterialPropsPanel) bpy.utils.unregister_class(MaterialPropsPanel)
bpy.utils.unregister_class(ArmoryPlayerPanel) bpy.utils.unregister_class(ArmoryPlayerPanel)
bpy.utils.unregister_class(ArmoryRenderPanel)
bpy.utils.unregister_class(ArmoryExporterPanel) bpy.utils.unregister_class(ArmoryExporterPanel)
bpy.utils.unregister_class(ArmoryProjectPanel) bpy.utils.unregister_class(ArmoryProjectPanel)
bpy.utils.unregister_class(ArmRenderPathPanel) bpy.utils.unregister_class(ArmRenderPathPanel)
bpy.utils.unregister_class(ArmBakePanel) bpy.utils.unregister_class(ArmBakePanel)
# bpy.utils.unregister_class(ArmVirtualInputPanel) # bpy.utils.unregister_class(ArmVirtualInputPanel)
bpy.utils.unregister_class(ArmoryPlayButton) bpy.utils.unregister_class(ArmoryPlayButton)
bpy.utils.unregister_class(ArmoryPlayInViewportButton)
bpy.utils.unregister_class(ArmoryStopButton) bpy.utils.unregister_class(ArmoryStopButton)
bpy.utils.unregister_class(ArmoryBuildButton) bpy.utils.unregister_class(ArmoryBuildButton)
bpy.utils.unregister_class(ArmoryBuildProjectButton) bpy.utils.unregister_class(ArmoryBuildProjectButton)
bpy.utils.unregister_class(ArmoryPatchProjectButton)
bpy.utils.unregister_class(ArmoryPatchButton)
bpy.utils.unregister_class(ArmoryOpenProjectFolderButton) bpy.utils.unregister_class(ArmoryOpenProjectFolderButton)
bpy.utils.unregister_class(ArmoryKodeStudioButton) bpy.utils.unregister_class(ArmoryKodeStudioButton)
bpy.utils.unregister_class(CleanMenu) bpy.utils.unregister_class(CleanMenu)
bpy.utils.unregister_class(CleanButtonMenu) bpy.utils.unregister_class(CleanButtonMenu)
bpy.utils.unregister_class(ArmoryCleanProjectButton) bpy.utils.unregister_class(ArmoryCleanProjectButton)
bpy.utils.unregister_class(ArmoryPublishProjectButton) bpy.utils.unregister_class(ArmoryPublishProjectButton)
bpy.utils.unregister_class(ArmoryRenderButton)
bpy.utils.unregister_class(ArmoryRenderAnimButton)
bpy.utils.unregister_class(ArmoryGenerateNavmeshButton) bpy.utils.unregister_class(ArmoryGenerateNavmeshButton)
bpy.utils.unregister_class(ArmNavigationPanel) bpy.utils.unregister_class(ArmNavigationPanel)
bpy.utils.unregister_class(ArmGenLodButton) bpy.utils.unregister_class(ArmGenLodButton)

View file

@ -1,73 +0,0 @@
# Embedded player in Armory Space
import bpy
from bpy.types import Header
from bpy.app.translations import contexts as i18n_contexts
import arm.utils
import arm.make as make
import arm.make_state as state
import arm.log as log
class ArmorySpaceHeader(Header):
bl_space_type = 'VIEW_ARMORY'
def draw(self, context):
layout = self.layout
view = context.space_data
obj = context.active_object
toolsettings = context.tool_settings
row = layout.row(align=True)
row.template_header()
# row.operator('arm.space_stop', icon='MESH_PLANE')
# if state.is_paused:
# row.operator('arm.space_resume', icon="PLAY")
# else:
# row.operator('arm.space_pause', icon="PAUSE")
# layout.label(log.header_info_text)
# class ArmorySpaceStopButton(bpy.types.Operator):
# '''Switch back to 3D view'''
# bl_idname = 'arm.space_stop'
# bl_label = 'Stop'
# def execute(self, context):
# area = bpy.context.area
# if area == None:
# area = state.play_area
# area.type = 'VIEW_3D'
# state.is_paused = False
# log.clear()
# return{'FINISHED'}
# class ArmorySpacePauseButton(bpy.types.Operator):
# '''Pause rendering'''
# bl_idname = 'arm.space_pause'
# bl_label = 'Pause'
# def execute(self, context):
# state.is_paused = True
# return{'FINISHED'}
# class ArmorySpaceResumeButton(bpy.types.Operator):
# '''Resume rendering'''
# bl_idname = 'arm.space_resume'
# bl_label = 'Resume'
# def execute(self, context):
# state.is_paused = False
# return{'FINISHED'}
def register():
if arm.utils.with_krom():
bpy.utils.register_class(ArmorySpaceHeader)
# bpy.utils.register_class(ArmorySpaceStopButton)
# bpy.utils.register_class(ArmorySpacePauseButton)
# bpy.utils.register_class(ArmorySpaceResumeButton)
def unregister():
if arm.utils.with_krom():
bpy.utils.unregister_class(ArmorySpaceHeader)
# bpy.utils.unregister_class(ArmorySpaceStopButton)
# bpy.utils.unregister_class(ArmorySpacePauseButton)
# bpy.utils.unregister_class(ArmorySpaceResumeButton)

View file

@ -9,6 +9,7 @@ import subprocess
import webbrowser import webbrowser
import arm.lib.armpack import arm.lib.armpack
import arm.make_state as state import arm.make_state as state
import arm.log as log
def write_arm(filepath, output): def write_arm(filepath, output):
if filepath.endswith('.zip'): if filepath.endswith('.zip'):
@ -86,23 +87,27 @@ def get_rp():
wrd = bpy.data.worlds['Arm'] wrd = bpy.data.worlds['Arm']
return wrd.arm_rplist[wrd.arm_rplist_index] return wrd.arm_rplist[wrd.arm_rplist_index]
def bundled_sdk_path():
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/'
def get_sdk_path(): def get_sdk_path():
user_preferences = bpy.context.user_preferences user_preferences = bpy.context.user_preferences
addon_prefs = user_preferences.addons['armory'].preferences addon_prefs = user_preferences.addons["armory"].preferences
if with_krom() and addon_prefs.sdk_bundled: p = bundled_sdk_path()
if get_os() == 'mac': if os.path.exists(p) and addon_prefs.sdk_bundled:
# SDK on MacOS is located in .app folder due to security return p
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: else:
return addon_prefs.sdk_path return addon_prefs.sdk_path
@ -131,19 +136,11 @@ def get_code_editor():
addon_prefs = user_preferences.addons['armory'].preferences addon_prefs = user_preferences.addons['armory'].preferences
return 'kodestudio' if not hasattr(addon_prefs, 'code_editor') else addon_prefs.code_editor return 'kodestudio' if not hasattr(addon_prefs, 'code_editor') else addon_prefs.code_editor
# def get_kha_version():
# user_preferences = bpy.context.user_preferences
# addon_prefs = user_preferences.addons['armory'].preferences
# return 'bundled' if not hasattr(addon_prefs, 'kha_version') else addon_prefs.kha_version
def get_ui_scale(): def get_ui_scale():
user_preferences = bpy.context.user_preferences user_preferences = bpy.context.user_preferences
addon_prefs = user_preferences.addons['armory'].preferences addon_prefs = user_preferences.addons['armory'].preferences
return 1.0 if not hasattr(addon_prefs, 'ui_scale') else addon_prefs.ui_scale return 1.0 if not hasattr(addon_prefs, 'ui_scale') else addon_prefs.ui_scale
def get_ease_viewport_camera():
return True
def get_save_on_build(): def get_save_on_build():
user_preferences = bpy.context.user_preferences user_preferences = bpy.context.user_preferences
addon_prefs = user_preferences.addons['armory'].preferences addon_prefs = user_preferences.addons['armory'].preferences
@ -341,6 +338,8 @@ def fetch_bundled_trait_props():
fetch_prop(o) fetch_prop(o)
def update_trait_groups(): def update_trait_groups():
if not hasattr(bpy.data, 'groups'):
return
for g in bpy.data.groups: for g in bpy.data.groups:
if g.name.startswith('Trait|'): if g.name.startswith('Trait|'):
bpy.data.groups.remove(g) bpy.data.groups.remove(g)
@ -410,24 +409,17 @@ def logic_editor_space():
return None return None
def voxel_support(): def voxel_support():
b = state.in_viewport == False or bpy.app.version >= (2, 80, 1) return state.target != 'html5'
if state.target == 'html5':
b = False
return b
krom_found = False v8_found = False
def with_krom(): def with_v8():
global krom_found global v8_found
return krom_found return v8_found
glslver = 110
def glsl_version():
global glslver
return glslver
def check_saved(self): def check_saved(self):
if bpy.data.filepath == "": if bpy.data.filepath == "":
self.report({"ERROR"}, "Save blend file first") msg = "Save blend file first"
self.report({"ERROR"}, msg) if self != None else log.print_info(msg)
return False return False
return True return True
@ -443,7 +435,8 @@ def check_path(s):
def check_sdkpath(self): def check_sdkpath(self):
s = get_sdk_path() s = get_sdk_path()
if check_path(s) == False: if check_path(s) == False:
self.report({"ERROR"}, "SDK path '{0}' contains special characters. Please move SDK to different path for now.".format(s)) msg = "SDK path '{0}' contains special characters. Please move SDK to different path for now.".format(s)
self.report({"ERROR"}, msg) if self != None else log.print_info(msg)
return False return False
else: else:
return True return True
@ -451,20 +444,19 @@ def check_sdkpath(self):
def check_projectpath(self): def check_projectpath(self):
s = get_fp() s = get_fp()
if check_path(s) == False: if check_path(s) == False:
self.report({"WARNING"}, "Project path '{0}' contains special characters, build process may fail.".format(s)) msg = "Project path '{0}' contains special characters, build process may fail.".format(s)
self.report({"ERROR"}, msg) if self != None else log.print_info(msg)
return False return False
else: else:
return True return True
def check_engine(self): def check_engine(self):
if bpy.context == None or bpy.context.scene == None: if bpy.context == None or bpy.context.scene == None:
return return False
if bpy.app.version >= (2, 80, 1): engine = bpy.context.scene.render.engine
engine = bpy.context.scene.view_render.engine if engine != 'CYCLES' and engine != 'BLENDER_EEVEE' and engine != 'ARMORY':
else: msg = "Switch to Armory, Cycles or Eevee engine first"
engine = bpy.context.scene.render.engine self.report({"ERROR"}, msg) if self != None else log.print_info(msg)
if engine != 'CYCLES' and engine != 'BLENDER_EEVEE':
self.report({"ERROR"}, "Switch to Cycles or Eevee engine first")
return False return False
return True return True
@ -618,13 +610,14 @@ def check_default_rp():
wrd.arm_rplist_index = 0 wrd.arm_rplist_index = 0
def register(): def register():
global krom_found global v8_found
global glslver try:
import importlib.util engine = bpy.context.scene.render.engine
if importlib.util.find_spec('barmory') != None: bpy.context.scene.render.engine = 'ARMORY'
krom_found = True bpy.context.scene.render.engine = engine
import bgl v8_found = True
glslver = int(bgl.glGetString(bgl.GL_SHADING_LANGUAGE_VERSION).split(' ', 1)[0].replace('.', '')) except:
pass
def unregister(): def unregister():
pass pass

View file

@ -144,7 +144,6 @@ project.addSources('Sources');
f.write("project.addParameter('-dce full');\n") f.write("project.addParameter('-dce full');\n")
if in_viewport: if in_viewport:
assets.add_khafile_def('arm_viewport')
import_traits.append('armory.trait.internal.Bridge') import_traits.append('armory.trait.internal.Bridge')
import_traits = list(set(import_traits)) import_traits = list(set(import_traits))
@ -152,13 +151,6 @@ project.addSources('Sources');
f.write("project.addParameter('" + import_traits[i] + "');\n") f.write("project.addParameter('" + import_traits[i] + "');\n")
f.write("""project.addParameter("--macro keep('""" + import_traits[i] + """')");\n""") f.write("""project.addParameter("--macro keep('""" + import_traits[i] + """')");\n""")
if state.is_render:
assets.add_khafile_def('arm_render')
if state.is_render_anim:
assets.add_khafile_def('arm_render_anim')
if not os.path.exists('Libraries/iron_format'):
f.write(add_armory_library(sdk_path + '/lib/', 'iron_format'))
shaderload = state.target == 'krom' or state.target == 'html5' shaderload = state.target == 'krom' or state.target == 'html5'
if arm.utils.get_player_gapi() != 'opengl': # TODO: shader from source for d3d11 if arm.utils.get_player_gapi() != 'opengl': # TODO: shader from source for d3d11
shaderload = False shaderload = False
@ -166,11 +158,6 @@ project.addSources('Sources');
# Load shaders manually # Load shaders manually
assets.add_khafile_def('arm_shaderload') assets.add_khafile_def('arm_shaderload')
# sceneload = state.target == 'krom'
# if wrd.arm_play_live_patch and is_play and in_viewport and sceneload:
# Scene patch
# assets.add_khafile_def('arm_sceneload')
shader_references = sorted(list(set(assets.shaders))) shader_references = sorted(list(set(assets.shaders)))
for ref in shader_references: for ref in shader_references:
ref = ref.replace('\\', '/') ref = ref.replace('\\', '/')
@ -338,13 +325,6 @@ class Main {
f.write(""" f.write("""
public static function main() { public static function main() {
iron.object.BoneAnimation.skinMaxBones = """ + str(rpdat.arm_skin_max_bones) + """; iron.object.BoneAnimation.skinMaxBones = """ + str(rpdat.arm_skin_max_bones) + """;
""")
# TODO: deprecated
if in_viewport:
f.write("""
untyped __js__("Krom.setPenDownCallback = function() { };");
untyped __js__("Krom.setPenUpCallback = function() { };");
untyped __js__("Krom.setPenMoveCallback = function() { };");
""") """)
if rpdat.rp_shadowmap_cascades != '1': if rpdat.rp_shadowmap_cascades != '1':
f.write(""" f.write("""
@ -380,7 +360,7 @@ class Main {
if (windowMode == kha.WindowMode.Fullscreen) { windowMode = kha.WindowMode.BorderlessWindow; config.window_w = kha.Display.width(0); config.window_h = kha.Display.height(0); } if (windowMode == kha.WindowMode.Fullscreen) { windowMode = kha.WindowMode.BorderlessWindow; config.window_w = kha.Display.width(0); config.window_h = kha.Display.height(0); }
""") """)
# Cap window size to desktop resolution, otherwise the window may not get opened # Cap window size to desktop resolution, otherwise the window may not get opened
if not in_viewport and not state.is_render: if not in_viewport:
f.write(""" f.write("""
else { config.window_w = Std.int(Math.min(config.window_w, kha.Display.width(0))); config.window_h = Std.int(Math.min(config.window_h, kha.Display.height(0))); } else { config.window_w = Std.int(Math.min(config.window_w, kha.Display.width(0))); config.window_h = Std.int(Math.min(config.window_h, kha.Display.height(0))); }
""") """)
@ -404,11 +384,6 @@ class Main {
f.write(""" f.write("""
iron.Scene.setActive('""" + arm.utils.safestr(scene_name) + scene_ext + """', function(object:iron.object.Object) { iron.Scene.setActive('""" + arm.utils.safestr(scene_name) + scene_ext + """', function(object:iron.object.Object) {
""") """)
# if arm.utils.with_krom() and in_viewport and is_play:
# if is_play or (state.target == 'html5' and not is_publish):
# f.write("""
# object.addTrait(new armory.trait.internal.SpaceArmory());
# """)
# Detect custom render path # Detect custom render path
pathpack = 'armory' pathpack = 'armory'

View file

@ -10,7 +10,6 @@ import arm.props_renderpath
import arm.props import arm.props
import arm.props_ui import arm.props_ui
import arm.handlers import arm.handlers
import arm.space_armory
import arm.utils import arm.utils
import arm.keymap import arm.keymap
@ -31,7 +30,6 @@ def register():
arm.props.register() arm.props.register()
arm.props_ui.register() arm.props_ui.register()
arm.nodes_logic.register() arm.nodes_logic.register()
arm.space_armory.register()
arm.keymap.register() arm.keymap.register()
arm.handlers.register() arm.handlers.register()
@ -52,4 +50,3 @@ def unregister():
arm.props_exporter.unregister() arm.props_exporter.unregister()
arm.props_bake.unregister() arm.props_bake.unregister()
arm.props_renderpath.unregister() arm.props_renderpath.unregister()
arm.space_armory.unregister()

View file

@ -1,3 +1,3 @@
*(optional - drag & drop zipped .blend file here)* *(drag & drop zipped .blend file here)*