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
}
public static inline function getRenderCaptureFormat():String {
#if (rp_rendercapture_format == "8bit")
return "RGBA32";
#elseif (rp_rendercapture_format == "16bit")
return "RGBA64";
#elseif (rp_rendercapture_format == "32bit")
return "RGBA128";
#else
return "RGBA32";
#end
}
// public static inline function getRenderCaptureFormat():String {
// #if (rp_rendercapture_format == "8bit")
// return "RGBA32";
// #elseif (rp_rendercapture_format == "16bit")
// return "RGBA64";
// #elseif (rp_rendercapture_format == "32bit")
// return "RGBA128";
// #else
// return "RGBA32";
// #end
// }
#if (rp_gi == "Voxel GI")
public static function computeVoxelsBegin() {

View file

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

View file

@ -52,19 +52,19 @@ class RenderPathForward {
}
#end
#if rp_rendercapture
{
var t = new RenderTargetRaw();
t.name = "capture";
t.width = 0;
t.height = 0;
t.format = Inc.getRenderCaptureFormat();
path.createRenderTarget(t);
#if rp_compositornodes
path.loadShader("shader_datas/copy_pass/copy_pass");
#end
}
#end
// #if rp_rendercapture
// {
// var t = new RenderTargetRaw();
// t.name = "capture";
// t.width = 0;
// t.height = 0;
// t.format = Inc.getRenderCaptureFormat();
// path.createRenderTarget(t);
// #if rp_compositornodes
// path.loadShader("shader_datas/copy_pass/copy_pass");
// #end
// }
// #end
#if ((rp_supersampling == 4) || (rp_antialiasing == "SMAA") || (rp_antialiasing == "TAA"))
{
@ -488,21 +488,21 @@ class RenderPathForward {
#if (rp_supersampling == 4)
{
#if rp_rendercapture
var finalTarget = "capture";
#else
// #if rp_rendercapture
// var finalTarget = "capture";
// #else
var finalTarget = "";
#end
// #end
path.setTarget(finalTarget);
path.bindTarget(framebuffer, "tex");
path.drawShader("shader_datas/supersample_resolve/supersample_resolve");
}
#elseif (rp_rendercapture)
{
path.setTarget("capture");
path.bindTarget(framebuffer, "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
}
// #elseif (rp_rendercapture)
// {
// path.setTarget("capture");
// path.bindTarget(framebuffer, "tex");
// path.drawShader("shader_datas/copy_pass/copy_pass");
// }
#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 = {
"name": "Armory",
"category": "Render",
"location": "Properties -> Render -> Armory Player",
"location": "Properties -> Render -> Armory",
"description": "3D Game Engine for Blender",
"author": "Armory3D.org",
"version": (13, 0, 0),
"version": (14, 0, 0),
"blender": (2, 79, 0),
"wiki_url": "http://armory3d.org/manual",
"tracker_url": "https://github.com/armory3d/armory/issues"
@ -24,8 +24,6 @@ from bpy.types import Operator, AddonPreferences
from bpy.props import *
from bpy.app.handlers import persistent
with_krom = False
def get_os():
s = platform.system()
if s == 'Windows':
@ -76,10 +74,6 @@ class ArmoryAddonPreferences(AddonPreferences):
items = [('kodestudio', 'Kode Studio', 'kodestudio'),
('default', 'System Default', 'default')],
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)
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="")
@ -92,11 +86,11 @@ class ArmoryAddonPreferences(AddonPreferences):
skip_update = BoolProperty(name="", default=False)
def draw(self, context):
global with_krom
self.skip_update = False
layout = self.layout
layout.label(text="Welcome to Armory! Click 'Save User Settings' at the bottom to keep Armory enabled.")
if with_krom:
p = bundled_sdk_path()
if os.path.exists(p):
layout.prop(self, "sdk_bundled")
if not self.sdk_bundled:
layout.prop(self, "sdk_path")
@ -124,24 +118,27 @@ class ArmoryAddonPreferences(AddonPreferences):
box.prop(self, "save_on_build")
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):
global with_krom
user_preferences = context.user_preferences
addon_prefs = user_preferences.addons["armory"].preferences
if with_krom and addon_prefs.sdk_bundled:
if get_os() == 'mac':
# SDK on MacOS is located in .app folder due to security
p = bpy.app.binary_path
if p.endswith('Contents/MacOS/blender'):
return p[:-len('Contents/MacOS/blender')] + '/armsdk/'
else:
return p[:-len('Contents/MacOS/./blender')] + '/armsdk/'
elif get_os() == 'linux':
# /blender
return bpy.app.binary_path.rsplit('/', 1)[0] + '/armsdk/'
else:
# /blender.exe
return bpy.app.binary_path.replace('\\', '/').rsplit('/', 1)[0] + '/armsdk/'
p = bundled_sdk_path()
if os.path.exists(p) and addon_prefs.sdk_bundled:
return p
else:
return addon_prefs.sdk_path
@ -172,6 +169,159 @@ class ArmAddonStartButton(bpy.types.Operator):
play_in_viewport = False
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)
if sdk_path == "":
self.report({"ERROR"}, "Configure SDK path first")
@ -183,7 +333,7 @@ class ArmAddonStartButton(bpy.types.Operator):
start.register()
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)
return {"FINISHED"}
@ -265,14 +415,10 @@ def draw_view3d_header(self, context):
layout.operator("arm_addon.start")
def register():
global with_krom
import importlib.util
if importlib.util.find_spec('barmory') != None:
with_krom = True
bpy.utils.register_module(__name__)
if hasattr(bpy.app.handlers, 'scene_update_post'):
bpy.app.handlers.scene_update_post.append(on_scene_update_post)
else: # 2.8
else:
bpy.types.VIEW3D_HT_header.append(draw_view3d_header)
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.mat_batch as mat_batch
import arm.make_renderpath as make_renderpath
import arm.material.cycles as cycles
NodeTypeNode = 0
NodeTypeBone = 1
@ -687,21 +688,19 @@ class ArmoryExporter:
return None
def get_viewport_view_matrix(self):
if self.play_area == None:
self.play_area = self.get_view3d_area()
if self.play_area == None:
play_area = self.get_view3d_area()
if play_area == None:
return None
for space in self.play_area.spaces:
for space in play_area.spaces:
if space.type == 'VIEW_3D':
return space.region_3d.view_matrix
return None
def get_viewport_projection_matrix(self):
if self.play_area == None:
self.play_area = self.get_view3d_area()
if self.play_area == None:
play_area = self.get_view3d_area()
if play_area == None:
return None, False
for space in self.play_area.spaces:
for space in play_area.spaces:
if space.type == 'VIEW_3D':
# return space.region_3d.perspective_matrix # pesp = window * view
return space.region_3d.window_matrix, space.region_3d.is_perspective
@ -1275,16 +1274,16 @@ class ArmoryExporter:
if has_tex:
# Get active uvmap
t0map = 0
uv_textures = exportMesh.uv_textures
if uv_textures != None:
if 'UVMap_baked' in uv_textures:
for i in range(0, len(uv_textures)):
if uv_textures[i].name == 'UVMap_baked':
uv_layers = exportMesh.uv_layers
if uv_layers != None:
if 'UVMap_baked' in uv_layers:
for i in range(0, len(uv_layers)):
if uv_layers[i].name == 'UVMap_baked':
t0map = i
break
else:
for i in range(0, len(uv_textures)):
if uv_textures[i].active_render:
for i in range(0, len(uv_layers)):
if uv_layers[i].active_render:
t0map = i
break
t1map = 1 if t0map == 0 else 0
@ -1605,7 +1604,7 @@ class ArmoryExporter:
o['shadowmap_cube'] = True
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['strength'] = objref.energy
if o['type'] == 'point' or o['type'] == 'spot':
@ -1689,10 +1688,8 @@ class ArmoryExporter:
wrd = bpy.data.worlds['Arm']
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()
windowed = not ArmoryExporter.in_viewport
if proj != None and is_persp and (pw == 0 or windowed):
if proj != None and is_persp:
self.extract_projection(o, proj, with_planes=False)
if objref.type != 'PERSP':
@ -1764,6 +1761,32 @@ class ArmoryExporter:
o['override_context'] = {}
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):
wrd = bpy.data.worlds['Arm']
@ -1788,6 +1811,12 @@ class ArmoryExporter:
if material == None:
continue
# Recache material
signature = self.get_signature(material)
if signature != material.signature:
material.is_cached = False
material.signature = signature
o = {}
o['name'] = arm.utils.asset_name(material)
@ -1975,12 +2004,11 @@ class ArmoryExporter:
self.output['mesh_datas'] = [];
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()
self.output = {}
self.filepath = filepath
self.play_area = play_area
self.scene = context.scene if scene == None else scene
print('Exporting ' + arm.utils.asset_name(self.scene))
@ -1989,12 +2017,6 @@ class ArmoryExporter:
self.beginFrame = self.scene.frame_start
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.bobjectBoneArray = {}
self.meshArray = {}
@ -2020,7 +2042,11 @@ class ArmoryExporter:
self.preprocess()
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:
scene_objects = self.scene.objects
for bobject in scene_objects:
@ -2131,18 +2157,6 @@ class ArmoryExporter:
o['near_plane'] = 0.1
o['far_plane'] = 100.0
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['frustum_culling'] = True
o['clear_color'] = self.get_camera_clear_color()
@ -2163,7 +2177,7 @@ class ArmoryExporter:
navigation_trait = {}
navigation_trait['type'] = 'Script'
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)
self.output['objects'].append(o)
self.output['camera_ref'] = 'DefaultCamera'
@ -2304,8 +2318,6 @@ class ArmoryExporter:
ArmoryExporter.export_ui = False
if not hasattr(ArmoryExporter, 'compress_enabled'):
ArmoryExporter.compress_enabled = False
if not hasattr(ArmoryExporter, 'in_viewport'):
ArmoryExporter.in_viewport = False
if not hasattr(ArmoryExporter, 'import_traits'):
ArmoryExporter.import_traits = [] # Referenced traits
ArmoryExporter.option_mesh_only = False
@ -2430,7 +2442,7 @@ class ArmoryExporter:
navigation_trait = {}
navigation_trait['type'] = 'Script'
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)
# Map objects to materials, can be used in later stages

View file

@ -1,176 +1,56 @@
import bpy
import time
import os
import sys
import bpy
from bpy.app.handlers import persistent
import arm.utils
import arm.bridge as bridge
import arm.log as log
import arm.props as props
import arm.make as make
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_operator = None
redraw_ui = False
redraw_progress = False
first_update = True
v8_started = False
@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_operator
global redraw_ui
global redraw_progress
global first_update
global v8_started
if first_update == True: # Skip first one, object reports is_update_data
first_update = False
return
# Redraw at the start of 'next' frame
if redraw_ui and bpy.context.screen != None:
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D' or area.type == 'PROPERTIES':
area.tag_redraw()
redraw_ui = False
if redraw_progress and bpy.context.screen != None:
for area in bpy.context.screen.areas:
if area.type == 'INFO':
area.tag_redraw()
break
redraw_progress = False
# Redraw player
with_armory = bpy.context.scene.render.engine == 'ARMORY'
if with_armory:
play_area = None
if bpy.context.screen != None:
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
play_area = area
break
if play_area != None and play_area.spaces[0].shading.type == 'MATERIAL':
if not v8_started:
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
operators_changed = False
if len(ops) > 0 and last_operator != ops[-1]:
last_operator = ops[-1]
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'):
obj = bpy.context.active_object
if obj != None:
@ -178,7 +58,7 @@ def on_scene_update_post(context):
recache(obj)
if len(ops) > 0 and ops[-1].bl_idname == 'OBJECT_OT_transform_apply':
recache(obj)
# New children need to be recached
# New children
if obj.type == 'ARMATURE':
for c in obj.children:
if c.data != None and c.data.is_updated:
@ -194,7 +74,7 @@ def on_scene_update_post(context):
if operators_changed:
op_changed(ops[-1], obj)
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
else:
obj.active_material.is_cached = False
@ -205,6 +85,7 @@ def on_scene_update_post(context):
space.node_tree.is_cached = False
def recache(obj):
print('recacheee')
# Moving keyframes triggers is_updated_data..
if state.compileproc != None:
return
@ -282,8 +163,8 @@ def load_library(asset_name):
ref.use_fake_user = True
def register():
if hasattr(bpy.app.handlers, 'scene_update_post'):
bpy.app.handlers.scene_update_post.append(on_scene_update_post)
if hasattr(bpy.app.handlers, 'scene_update_pre'):
bpy.app.handlers.scene_update_pre.append(on_scene_update_pre)
bpy.app.handlers.save_pre.append(on_save_pre)
bpy.app.handlers.load_post.append(on_load_post)
# On windows, on_load_post is not called when opening .blend file from explorer
@ -292,7 +173,7 @@ def register():
reload_blend_data()
def unregister():
if hasattr(bpy.app.handlers, 'scene_update_post'):
bpy.app.handlers.scene_update_post.remove(on_scene_update_post)
if hasattr(bpy.app.handlers, 'scene_update_pre'):
bpy.app.handlers.scene_update_pre.remove(on_scene_update_pre)
bpy.app.handlers.save_pre.remove(on_save_pre)
bpy.app.handlers.load_post.remove(on_load_post)

View file

@ -1,4 +1,3 @@
# Key shortcuts
import bpy
import arm.props_ui as props_ui
import arm.utils
@ -9,11 +8,6 @@ def register():
wm = bpy.context.window_manager
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.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)
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 = ''
# header_info_text = ''
def clear():
global info_text
# global header_info_text
info_text = ''
# if arm.utils.with_krom():
# header_info_text = ''
def format_text(text):
return (text[:80] + '..') if len(text) > 80 else text # Limit str size
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)
def print_info(text):
global tag_redraw
global info_text
print(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):
print('Armory Warning: ' + text)

View file

@ -12,10 +12,10 @@ class GetVelocityNode(Node, ArmLogicTreeNode):
def init(self, context):
self.inputs.new('ArmNodeSocketObject', 'Object')
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.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]
add_node(GetVelocityNode, category='Physics')

View file

@ -20,11 +20,6 @@ import arm.log as log
import arm.lib.make_datas
import arm.lib.server
from arm.exporter import ArmoryExporter
import time
try:
import barmory
except ImportError:
pass
exporter = ArmoryExporter()
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']
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
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
ui_found = False
ArmoryExporter.compress_enabled = is_publish and wrd.arm_asset_compression
ArmoryExporter.in_viewport = in_viewport
for scene in bpy.data.scenes:
if scene.arm_export:
ext = '.zip' if (scene.arm_compress and is_publish) else '.arm'
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:
physics_found = True
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_scene = scene_name
def compile_project(target_name=None, watch=False, patch=False, no_project_file=False):
"""
:param no_project_file: Pass '--noproject' to kha make. In the future assets will be copied.
"""
def compile(target_name=None, watch=False, patch=False):
wrd = bpy.data.worlds['Arm']
fp = arm.utils.get_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()
cmd.append('-g')
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
is_linux = arm.utils.get_os() == 'linux'
is_native = kha_target_name == 'krom' or kha_target_name == ''
if is_linux and is_native and not state.in_viewport and not arm.utils.get_legacy_shaders():
if arm.utils.get_legacy_shaders() and not state.in_viewport:
cmd.append('--shaderversion')
cmd.append('110')
else:
cmd.append('--shaderversion')
cmd.append('330')
@ -271,10 +254,7 @@ def compile_project(target_name=None, watch=False, patch=False, no_project_file=
print("Running: ", cmd)
state.compileproc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
if state.playproc == None:
if state.in_viewport:
mode = 'play_viewport'
else:
mode = 'play'
mode = 'play_viewport' if state.in_viewport else 'play'
else:
mode = 'build'
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()
return state.compileproc
else:
if no_project_file:
cmd.append('--noproject')
print("Running: ", 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
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.in_viewport = in_viewport
# 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()
log.clear()
@ -325,6 +319,7 @@ def build_project(is_play=False, is_publish=False, is_render=False, is_render_an
os.chdir(fp)
# Create directories
wrd = bpy.data.worlds['Arm']
sources_path = 'Sources/' + arm.utils.safestr(wrd.arm_project_package)
if not os.path.exists(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):
shutil.copy(fn, arm.utils.build_dir() + dest + os.path.basename(fn))
if state.playproc == None:
log.print_progress(50)
def stop_project():
if state.playproc != None:
state.playproc.terminate()
@ -386,31 +378,24 @@ def watch_play():
else:
line += char
state.playproc = None
state.playproc_finished = True
log.clear()
def watch_compile(mode):
state.compileproc.wait()
log.print_progress(100)
print('Finished in ' + str(time.time() - profile_time))
if state.compileproc == None: ##
return
result = state.compileproc.poll()
state.compileproc = None
state.compileproc_finished = True
if result == 0:
bpy.data.worlds['Arm'].arm_recompile = False
state.compileproc_success = True
on_compiled(mode)
else:
state.compileproc_success = False
log.print_info('Build failed, check console')
def watch_patch(mode):
state.compileproc.wait()
log.print_progress(100)
state.compileproc = None
state.compileproc_finished = True
on_compiled(mode)
def runtime_to_target(in_viewport):
@ -430,21 +415,17 @@ def get_khajs_path(in_viewport, target):
else: # Browser
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 code_parsed
wrd = bpy.data.worlds['Arm']
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)
# 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)
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
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'
if state.target == 'native':
state.compileproc = compile_project(target_name='--run')
state.compileproc = compile(target_name='--run')
elif state.target == 'krom':
if in_viewport:
mode = 'play_viewport'
state.compileproc = compile_project(target_name='krom')
state.compileproc = compile(target_name='krom')
else: # Browser
state.compileproc = compile_project(target_name='html5')
state.compileproc = compile(target_name='html5')
threading.Timer(0.1, watch_compile, [mode]).start()
else: # kha.js up to date
state.recompiled = False
compile_project(patch=True)
compile(patch=True)
def on_compiled(mode): # build, play, play_viewport, publish
log.clear()
wrd = bpy.data.worlds['Arm']
# Launch project in new window
if mode == 'play':
if mode == 'play_viewport':
open(arm.utils.get_fp_build() + '/krom/krom.lock', 'w').close()
elif mode == 'play':
if wrd.arm_play_runtime == 'Browser':
# Start server
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
args.append('--nosound')
if state.is_render:
args.append('--nowindow')
args.append('--stdout')
args.append(arm.utils.get_fp_build() + '/krom.txt')
state.playproc = subprocess.Popen(args, stderr=subprocess.PIPE)
@ -610,7 +578,7 @@ def on_compiled(mode): # build, play, play_viewport, publish
else:
print('Exported makefiles to ' + files_path + '-build')
def clean_project():
def clean():
os.chdir(arm.utils.get_fp())
wrd = bpy.data.worlds['Arm']
@ -646,11 +614,3 @@ def clean_project():
mat.is_cached = False
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_light')
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:
assets.add_khafile_def('rp_volumetriclight')

View file

@ -1,8 +1,6 @@
target = 'krom'
last_target = 'krom'
in_viewport = False
is_export = False
export_gapi = ''
last_in_viewport = False
last_resx = 0
@ -13,13 +11,6 @@ last_scene = ''
last_world_defs = ''
playproc = 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 = []
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_overlay 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
def traverse_tree2(node, ar):

View file

@ -9,10 +9,6 @@ import arm.utils
import arm.make
import arm.props_renderpath as props_renderpath
import arm.proxy
try:
import barmory
except ImportError:
pass
# Armory version
arm_version = '0.4'
@ -78,7 +74,6 @@ def proxy_sync_traits(self, context):
def init_properties():
global arm_version
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_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)
@ -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_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_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(
items=[('Scene', 'Scene', 'Scene'),
('Viewport', 'Viewport', 'Viewport'),
@ -198,8 +191,6 @@ def init_properties():
bpy.types.Speaker.arm_stream = BoolProperty(name="Stream", description="Stream this sound", default=False)
# 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_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_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)
@ -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_turbidity = FloatProperty(name="Turbidity", default=1.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_receive_shadow = BoolProperty(name="Receive Shadow", default=True)
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)
wrd.arm_version = arm_version
wrd.arm_commit = arm_commit
arm.make.clean_project()
# Set url for embedded player
if arm.utils.with_krom():
barmory.set_files_location(arm.utils.get_fp_build() + '/krom')
arm.make.clean()
def register():
init_properties()

View file

@ -36,7 +36,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False
rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Linear'
@ -69,7 +68,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False
rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Anisotropic'
@ -101,7 +99,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False
rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Anisotropic'
@ -135,7 +132,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False
rpdat.rp_bloom = True
rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = True
rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display'
rpdat.arm_material_model = 'Full'
@ -169,7 +165,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False
rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Point'
@ -202,7 +197,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False
rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display'
rpdat.arm_texture_filter = 'Linear'
@ -238,7 +232,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False
rpdat.rp_bloom = True
rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display'
rpdat.arm_material_model = 'Full'
@ -272,7 +265,6 @@ def update_preset(self, context):
rpdat.rp_dfgi = False
rpdat.rp_bloom = False
rpdat.rp_eyeadapt = False
rpdat.rp_rendercapture = False
rpdat.rp_motionblur = 'Off'
rpdat.arm_rp_resolution = 'Display'
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_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_rendercapture = BoolProperty(name="Render Capture", description="Save output as render result", default=False, update=update_renderpath)
rp_motionblur = EnumProperty(
items=[('Off', 'Off', 'Off'),
('Camera', 'Camera', 'Camera'),

View file

@ -202,6 +202,7 @@ class InvalidateMaterialCacheButton(bpy.types.Operator):
def execute(self, context):
context.material.is_cached = False
context.material.signature = ''
return{'FINISHED'}
class InvalidateGPCacheButton(bpy.types.Operator):
@ -289,34 +290,13 @@ class ArmoryPlayerPanel(bpy.types.Panel):
row.operator("arm.play", icon="PLAY")
else:
row.operator("arm.stop", icon="MESH_PLANE")
if state.playproc == None and state.krom_running == False:
row.operator("arm.build")
else:
row.operator("arm.patch")
row.operator("arm.build")
row.operator("arm.clean_menu")
row = layout.row()
row.prop(wrd, 'arm_play_runtime', 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):
bl_label = "Armory Exporter"
bl_space_type = "PROPERTIES"
@ -330,7 +310,7 @@ class ArmoryExporterPanel(bpy.types.Panel):
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.operator("arm.build_project")
row.operator("arm.patch_project")
# row.operator("arm.patch_project")
row.operator("arm.publish_project", icon="EXPORT")
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_dce')
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.prop(wrd, 'arm_cache_shaders')
col.prop(wrd, 'arm_cache_compiler')
@ -515,57 +490,9 @@ class ArmoryPlayButton(bpy.types.Operator):
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
make.play_project(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)
make.play(in_viewport=False)
assets.invalidate_enabled = True
return{'FINISHED'}
@ -598,8 +525,8 @@ class ArmoryBuildButton(bpy.types.Operator):
state.target = make.runtime_to_target(in_viewport=False)
state.is_export = False
assets.invalidate_enabled = False
make.build_project()
make.compile_project(watch=True)
make.build()
make.compile(watch=True)
assets.invalidate_enabled = True
return{'FINISHED'}
@ -636,53 +563,8 @@ class ArmoryBuildProjectButton(bpy.types.Operator):
state.is_export = True
assets.invalidate_shader_cache(None, None)
assets.invalidate_enabled = False
make.build_project()
make.compile_project(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)
make.build()
make.compile(watch=True)
state.is_export = False
wrd.arm_rplist_index = rplist_index
assets.invalidate_enabled = True
@ -720,28 +602,17 @@ class ArmoryPublishProjectButton(bpy.types.Operator):
wrd.arm_rplist_index = i
break
make.clean_project()
make.clean()
state.target = item.arm_project_target
state.is_export = True
assets.invalidate_enabled = False
make.build_project(is_publish=True)
make.compile_project(watch=True)
make.build(is_publish=True)
make.compile(watch=True)
state.is_export = False
wrd.arm_rplist_index = rplist_index
assets.invalidate_enabled = True
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):
'''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):
return {"CANCELLED"}
make.clean_project()
make.clean()
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):
layout = self.layout
if state.playproc == None and state.compileproc == None:
if arm.utils.with_krom():
layout.operator("arm.play_in_viewport", icon="PLAY")
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)
if state.compileproc != None:
self.layout.label('Compiling..')
elif log.info_text != '':
self.layout.label(log.info_text)
class ArmRenderPathPanel(bpy.types.Panel):
bl_label = "Armory Render Path"
@ -1486,27 +1279,21 @@ def register():
bpy.utils.register_class(InvalidateGPCacheButton)
bpy.utils.register_class(MaterialPropsPanel)
bpy.utils.register_class(ArmoryPlayerPanel)
bpy.utils.register_class(ArmoryRenderPanel)
bpy.utils.register_class(ArmoryExporterPanel)
bpy.utils.register_class(ArmoryProjectPanel)
bpy.utils.register_class(ArmRenderPathPanel)
bpy.utils.register_class(ArmBakePanel)
# bpy.utils.register_class(ArmVirtualInputPanel)
bpy.utils.register_class(ArmoryPlayButton)
bpy.utils.register_class(ArmoryPlayInViewportButton)
bpy.utils.register_class(ArmoryStopButton)
bpy.utils.register_class(ArmoryBuildButton)
bpy.utils.register_class(ArmoryBuildProjectButton)
bpy.utils.register_class(ArmoryPatchProjectButton)
bpy.utils.register_class(ArmoryPatchButton)
bpy.utils.register_class(ArmoryOpenProjectFolderButton)
bpy.utils.register_class(ArmoryKodeStudioButton)
bpy.utils.register_class(CleanMenu)
bpy.utils.register_class(CleanButtonMenu)
bpy.utils.register_class(ArmoryCleanProjectButton)
bpy.utils.register_class(ArmoryPublishProjectButton)
bpy.utils.register_class(ArmoryRenderButton)
bpy.utils.register_class(ArmoryRenderAnimButton)
bpy.utils.register_class(ArmoryGenerateNavmeshButton)
bpy.utils.register_class(ArmNavigationPanel)
bpy.utils.register_class(ArmGenLodButton)
@ -1518,14 +1305,10 @@ def register():
bpy.utils.register_class(ArmProxyApplyAllButton)
bpy.utils.register_class(ArmSyncProxyButton)
bpy.utils.register_class(ArmPrintTraitsButton)
bpy.types.VIEW3D_HT_header.append(draw_view3d_header)
bpy.types.INFO_HT_header.append(draw_info_header)
def unregister():
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(ModifiersPropsPanel)
bpy.utils.unregister_class(ParticlesPropsPanel)
@ -1537,27 +1320,21 @@ def unregister():
bpy.utils.unregister_class(InvalidateGPCacheButton)
bpy.utils.unregister_class(MaterialPropsPanel)
bpy.utils.unregister_class(ArmoryPlayerPanel)
bpy.utils.unregister_class(ArmoryRenderPanel)
bpy.utils.unregister_class(ArmoryExporterPanel)
bpy.utils.unregister_class(ArmoryProjectPanel)
bpy.utils.unregister_class(ArmRenderPathPanel)
bpy.utils.unregister_class(ArmBakePanel)
# bpy.utils.unregister_class(ArmVirtualInputPanel)
bpy.utils.unregister_class(ArmoryPlayButton)
bpy.utils.unregister_class(ArmoryPlayInViewportButton)
bpy.utils.unregister_class(ArmoryStopButton)
bpy.utils.unregister_class(ArmoryBuildButton)
bpy.utils.unregister_class(ArmoryBuildProjectButton)
bpy.utils.unregister_class(ArmoryPatchProjectButton)
bpy.utils.unregister_class(ArmoryPatchButton)
bpy.utils.unregister_class(ArmoryOpenProjectFolderButton)
bpy.utils.unregister_class(ArmoryKodeStudioButton)
bpy.utils.unregister_class(CleanMenu)
bpy.utils.unregister_class(CleanButtonMenu)
bpy.utils.unregister_class(ArmoryCleanProjectButton)
bpy.utils.unregister_class(ArmoryPublishProjectButton)
bpy.utils.unregister_class(ArmoryRenderButton)
bpy.utils.unregister_class(ArmoryRenderAnimButton)
bpy.utils.unregister_class(ArmoryGenerateNavmeshButton)
bpy.utils.unregister_class(ArmNavigationPanel)
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 arm.lib.armpack
import arm.make_state as state
import arm.log as log
def write_arm(filepath, output):
if filepath.endswith('.zip'):
@ -86,23 +87,27 @@ def get_rp():
wrd = bpy.data.worlds['Arm']
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():
user_preferences = bpy.context.user_preferences
addon_prefs = user_preferences.addons['armory'].preferences
if with_krom() and addon_prefs.sdk_bundled:
if get_os() == 'mac':
# SDK on MacOS is located in .app folder due to security
p = bpy.app.binary_path
if p.endswith('Contents/MacOS/blender'):
return p[:-len('Contents/MacOS/blender')] + '/armsdk/'
else:
return p[:-len('Contents/MacOS/./blender')] + '/armsdk/'
elif get_os() == 'linux':
# /blender
return bpy.app.binary_path.rsplit('/', 1)[0] + '/armsdk/'
else:
# /blender.exe
return bpy.app.binary_path.replace('\\', '/').rsplit('/', 1)[0] + '/armsdk/'
addon_prefs = user_preferences.addons["armory"].preferences
p = bundled_sdk_path()
if os.path.exists(p) and addon_prefs.sdk_bundled:
return p
else:
return addon_prefs.sdk_path
@ -131,19 +136,11 @@ def get_code_editor():
addon_prefs = user_preferences.addons['armory'].preferences
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():
user_preferences = bpy.context.user_preferences
addon_prefs = user_preferences.addons['armory'].preferences
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():
user_preferences = bpy.context.user_preferences
addon_prefs = user_preferences.addons['armory'].preferences
@ -341,6 +338,8 @@ def fetch_bundled_trait_props():
fetch_prop(o)
def update_trait_groups():
if not hasattr(bpy.data, 'groups'):
return
for g in bpy.data.groups:
if g.name.startswith('Trait|'):
bpy.data.groups.remove(g)
@ -410,24 +409,17 @@ def logic_editor_space():
return None
def voxel_support():
b = state.in_viewport == False or bpy.app.version >= (2, 80, 1)
if state.target == 'html5':
b = False
return b
return state.target != 'html5'
krom_found = False
def with_krom():
global krom_found
return krom_found
glslver = 110
def glsl_version():
global glslver
return glslver
v8_found = False
def with_v8():
global v8_found
return v8_found
def check_saved(self):
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 True
@ -443,7 +435,8 @@ def check_path(s):
def check_sdkpath(self):
s = get_sdk_path()
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
else:
return True
@ -451,20 +444,19 @@ def check_sdkpath(self):
def check_projectpath(self):
s = get_fp()
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
else:
return True
def check_engine(self):
if bpy.context == None or bpy.context.scene == None:
return
if bpy.app.version >= (2, 80, 1):
engine = bpy.context.scene.view_render.engine
else:
engine = bpy.context.scene.render.engine
if engine != 'CYCLES' and engine != 'BLENDER_EEVEE':
self.report({"ERROR"}, "Switch to Cycles or Eevee engine first")
return False
engine = bpy.context.scene.render.engine
if engine != 'CYCLES' and engine != 'BLENDER_EEVEE' and engine != 'ARMORY':
msg = "Switch to Armory, Cycles or Eevee engine first"
self.report({"ERROR"}, msg) if self != None else log.print_info(msg)
return False
return True
@ -618,13 +610,14 @@ def check_default_rp():
wrd.arm_rplist_index = 0
def register():
global krom_found
global glslver
import importlib.util
if importlib.util.find_spec('barmory') != None:
krom_found = True
import bgl
glslver = int(bgl.glGetString(bgl.GL_SHADING_LANGUAGE_VERSION).split(' ', 1)[0].replace('.', ''))
global v8_found
try:
engine = bpy.context.scene.render.engine
bpy.context.scene.render.engine = 'ARMORY'
bpy.context.scene.render.engine = engine
v8_found = True
except:
pass
def unregister():
pass

View file

@ -144,7 +144,6 @@ project.addSources('Sources');
f.write("project.addParameter('-dce full');\n")
if in_viewport:
assets.add_khafile_def('arm_viewport')
import_traits.append('armory.trait.internal.Bridge')
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("--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'
if arm.utils.get_player_gapi() != 'opengl': # TODO: shader from source for d3d11
shaderload = False
@ -166,11 +158,6 @@ project.addSources('Sources');
# Load shaders manually
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)))
for ref in shader_references:
ref = ref.replace('\\', '/')
@ -338,13 +325,6 @@ class Main {
f.write("""
public static function main() {
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':
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); }
""")
# 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("""
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("""
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
pathpack = 'armory'

View file

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