Prop descriptions.
This commit is contained in:
parent
e8ce9f2030
commit
80b8bc3236
|
@ -27,7 +27,7 @@ class TimeNode extends FloatNode {
|
|||
function update() {
|
||||
|
||||
if (inputs[_enabled].b) {
|
||||
f += iron.sys.Time.delta * scale;
|
||||
f += iron.system.Time.delta * scale;
|
||||
|
||||
// Time out
|
||||
if (inputs[_stopTime].f > 0) {
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
package armory.sys;
|
||||
|
||||
typedef Audio = iron.sys.Audio;
|
|
@ -1,3 +0,0 @@
|
|||
package armory.sys;
|
||||
|
||||
typedef Input = iron.sys.Input;
|
|
@ -1,3 +0,0 @@
|
|||
package armory.sys;
|
||||
|
||||
typedef Storage = iron.sys.Storage;
|
|
@ -1,3 +0,0 @@
|
|||
package armory.sys;
|
||||
|
||||
typedef Time = iron.sys.Time;
|
|
@ -1,3 +0,0 @@
|
|||
package armory.sys;
|
||||
|
||||
typedef Tween = iron.sys.Tween;
|
|
@ -1,3 +0,0 @@
|
|||
package armory.sys;
|
||||
|
||||
typedef VR = iron.sys.VR;
|
3
Sources/armory/system/Audio.hx
Normal file
3
Sources/armory/system/Audio.hx
Normal file
|
@ -0,0 +1,3 @@
|
|||
package armory.system;
|
||||
|
||||
typedef Audio = iron.system.Audio;
|
3
Sources/armory/system/Input.hx
Normal file
3
Sources/armory/system/Input.hx
Normal file
|
@ -0,0 +1,3 @@
|
|||
package armory.system;
|
||||
|
||||
typedef Input = iron.system.Input;
|
3
Sources/armory/system/Storage.hx
Normal file
3
Sources/armory/system/Storage.hx
Normal file
|
@ -0,0 +1,3 @@
|
|||
package armory.system;
|
||||
|
||||
typedef Storage = iron.system.Storage;
|
3
Sources/armory/system/Time.hx
Normal file
3
Sources/armory/system/Time.hx
Normal file
|
@ -0,0 +1,3 @@
|
|||
package armory.system;
|
||||
|
||||
typedef Time = iron.system.Time;
|
3
Sources/armory/system/Tween.hx
Normal file
3
Sources/armory/system/Tween.hx
Normal file
|
@ -0,0 +1,3 @@
|
|||
package armory.system;
|
||||
|
||||
typedef Tween = iron.system.Tween;
|
3
Sources/armory/system/VR.hx
Normal file
3
Sources/armory/system/VR.hx
Normal file
|
@ -0,0 +1,3 @@
|
|||
package armory.system;
|
||||
|
||||
typedef VR = iron.system.VR;
|
|
@ -1,7 +1,7 @@
|
|||
package armory.trait;
|
||||
|
||||
import iron.Trait;
|
||||
import iron.sys.Input;
|
||||
import iron.system.Input;
|
||||
import iron.object.CameraObject;
|
||||
import iron.math.Vec4;
|
||||
import iron.math.Quat;
|
||||
|
|
|
@ -3,8 +3,8 @@ package armory.trait;
|
|||
import iron.math.Mat4;
|
||||
import iron.math.Vec4;
|
||||
import iron.Trait;
|
||||
import iron.sys.Input;
|
||||
import iron.sys.Time;
|
||||
import iron.system.Input;
|
||||
import iron.system.Time;
|
||||
import iron.object.Transform;
|
||||
import iron.object.CameraObject;
|
||||
import armory.trait.internal.RigidBody;
|
||||
|
|
|
@ -3,8 +3,8 @@ package armory.trait;
|
|||
import iron.math.Mat4;
|
||||
import iron.math.Vec4;
|
||||
import iron.Trait;
|
||||
import iron.sys.Input;
|
||||
import iron.sys.Time;
|
||||
import iron.system.Input;
|
||||
import iron.system.Time;
|
||||
import iron.object.Transform;
|
||||
import iron.object.CameraObject;
|
||||
import armory.trait.internal.RigidBody;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package armory.trait;
|
||||
|
||||
import iron.Trait;
|
||||
import iron.sys.Input;
|
||||
import iron.system.Input;
|
||||
import armory.trait.internal.RigidBody;
|
||||
import armory.trait.internal.PhysicsWorld;
|
||||
#if WITH_PHYSICS
|
||||
|
@ -42,7 +42,7 @@ class PhysicsDrag extends Trait {
|
|||
if (Input.started) {
|
||||
var b = physics.pickClosest(Input.x, Input.y);
|
||||
|
||||
if (b != null && b.mass > 0 && !b.body.ptr.isKinematicObject()) {
|
||||
if (b != null && b.mass > 0 && !b.body.ptr.isKinematicObject() && b.object.getTrait(PhysicsDrag) != null) {
|
||||
|
||||
setRays();
|
||||
pickedBody = b;
|
||||
|
@ -53,6 +53,13 @@ class PhysicsDrag extends Trait {
|
|||
var pickPos:BtVector3 = physics.rayCallback.value.m_hitPointWorld;
|
||||
#end
|
||||
|
||||
// var ct = b.object.transform.matrix;
|
||||
// var inv = iron.math.Mat4.identity();
|
||||
// inv.getInverse(ct);
|
||||
// var localPivotVec = new iron.math.Vec4(pickPos.x(), pickPos.y(), pickPos.z());
|
||||
// localPivotVec.applyMat4(inv);
|
||||
// var localPivot:BtVector3 = BtVector3.create(localPivotVec.x, localPivotVec.y, localPivotVec.z);
|
||||
|
||||
var ct = b.body.ptr.getCenterOfMassTransform();
|
||||
var inv = ct.inverse();
|
||||
|
||||
|
@ -94,6 +101,8 @@ class PhysicsDrag extends Trait {
|
|||
pickPos.z() - rayFrom.value.z());
|
||||
|
||||
pickDist = v.value.length();
|
||||
|
||||
Input.occupied = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,6 +113,8 @@ class PhysicsDrag extends Trait {
|
|||
pickConstraint = null;
|
||||
pickedBody = null;
|
||||
}
|
||||
|
||||
Input.occupied = false;
|
||||
}
|
||||
|
||||
else if (Input.touch) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import iron.Trait;
|
|||
import iron.object.Object;
|
||||
import iron.object.CameraObject;
|
||||
import iron.object.Transform;
|
||||
import iron.sys.Time;
|
||||
import iron.system.Time;
|
||||
import armory.trait.internal.PhysicsWorld;
|
||||
#if WITH_PHYSICS
|
||||
import haxebullet.Bullet;
|
||||
|
|
|
@ -2,8 +2,8 @@ package armory.trait;
|
|||
|
||||
import kha.Key;
|
||||
import iron.Trait;
|
||||
import iron.sys.Input;
|
||||
import iron.sys.Time;
|
||||
import iron.system.Input;
|
||||
import iron.system.Time;
|
||||
import iron.object.CameraObject;
|
||||
import iron.math.Vec4;
|
||||
import iron.math.Quat;
|
||||
|
|
|
@ -34,7 +34,7 @@ class Animation extends Trait {
|
|||
}
|
||||
|
||||
function update() {
|
||||
object.setAnimationParams(iron.sys.Time.delta);
|
||||
object.setAnimationParams(iron.system.Time.delta);
|
||||
}
|
||||
|
||||
public function play(trackName:String, onTrackComplete:Void->Void = null) {
|
||||
|
|
|
@ -3,10 +3,10 @@ package armory.trait.internal;
|
|||
import iron.Trait;
|
||||
import iron.object.Object;
|
||||
import iron.object.Transform;
|
||||
import iron.sys.Input;
|
||||
import iron.system.Input;
|
||||
import iron.math.RayCaster;
|
||||
|
||||
class SceneEditor extends Trait {
|
||||
class EditorSpace extends Trait {
|
||||
|
||||
var gizmo:Object;
|
||||
var arrowX:Object;
|
||||
|
@ -18,6 +18,8 @@ class SceneEditor extends Trait {
|
|||
var moveY = false;
|
||||
var moveZ = false;
|
||||
|
||||
static var first = true;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
|
@ -25,12 +27,25 @@ class SceneEditor extends Trait {
|
|||
}
|
||||
|
||||
function init() {
|
||||
gizmo = iron.Scene.active.getObject('ArrowGizmo');
|
||||
arrowX = iron.Scene.active.getObject('ArrowX');
|
||||
arrowY = iron.Scene.active.getObject('ArrowY');
|
||||
arrowZ = iron.Scene.active.getObject('ArrowZ');
|
||||
// gizmo = iron.Scene.active.getObject('ArrowGizmo');
|
||||
// arrowX = iron.Scene.active.getObject('ArrowX');
|
||||
// arrowY = iron.Scene.active.getObject('ArrowY');
|
||||
// arrowZ = iron.Scene.active.getObject('ArrowZ');
|
||||
|
||||
notifyOnUpdate(update);
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
kha.input.Keyboard.get().notify(onKeyDown, onKeyUp);
|
||||
}
|
||||
}
|
||||
|
||||
function onKeyDown(key: kha.Key, char: String) {
|
||||
// if (char == 'Z') trace('__arm|quit');
|
||||
if (key == kha.Key.ESC) trace('__arm|quit');
|
||||
}
|
||||
|
||||
function onKeyUp(key: kha.Key, char: String) {
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
@ -41,8 +56,8 @@ class SceneEditor extends Trait {
|
|||
var hit = RayCaster.getClosestBoxIntersect(transforms, Input.x, Input.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();
|
||||
// gizmo.transform.loc.set(loc.x, loc.y, loc.z);
|
||||
// gizmo.transform.buildMatrix();
|
||||
selected = hit;
|
||||
trace('__arm|select|' + selected.object.name);
|
||||
}
|
||||
|
@ -71,8 +86,8 @@ class SceneEditor extends Trait {
|
|||
|
||||
selected.buildMatrix();
|
||||
|
||||
gizmo.transform.loc.set(selected.loc.x, selected.loc.y, selected.loc.z);
|
||||
gizmo.transform.buildMatrix();
|
||||
// gizmo.transform.loc.set(selected.loc.x, selected.loc.y, selected.loc.z);
|
||||
// gizmo.transform.buildMatrix();
|
||||
}
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ class JSScriptAPI {
|
|||
|
||||
public static var App = iron.App;
|
||||
public static var Scene = iron.Scene;
|
||||
public static var Time = iron.sys.Time;
|
||||
public static var Time = iron.system.Time;
|
||||
public static var Object = iron.object.Object;
|
||||
public static var Data = iron.data.Data;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ package armory.trait.internal;
|
|||
import haxebullet.Bullet;
|
||||
#end
|
||||
import iron.Trait;
|
||||
import iron.sys.Time;
|
||||
import iron.system.Time;
|
||||
import iron.math.Vec4;
|
||||
import iron.math.RayCaster;
|
||||
|
||||
|
@ -65,7 +65,9 @@ class PhysicsWorld extends Trait {
|
|||
var gravity = iron.Scene.active.raw.gravity == null ? [0, 0, -9.81] : iron.Scene.active.raw.gravity;
|
||||
world.ptr.setGravity(BtVector3.create(gravity[0], gravity[1], gravity[2]).value);
|
||||
|
||||
notifyOnUpdate(update);
|
||||
Scene.active.notifyOnInit(function() {
|
||||
notifyOnUpdate(update);
|
||||
});
|
||||
}
|
||||
|
||||
public function addRigidBody(body:RigidBody) {
|
||||
|
|
|
@ -4,7 +4,7 @@ package armory.trait.internal;
|
|||
import haxebullet.Bullet;
|
||||
#end
|
||||
import iron.Trait;
|
||||
import iron.sys.Time;
|
||||
import iron.system.Time;
|
||||
import iron.math.Vec4;
|
||||
import iron.object.Transform;
|
||||
import iron.object.MeshObject;
|
||||
|
@ -41,9 +41,11 @@ class RigidBody extends Trait {
|
|||
this.friction = friction;
|
||||
this.collisionMargin = collisionMargin;
|
||||
|
||||
notifyOnInit(init);
|
||||
notifyOnLateUpdate(lateUpdate);
|
||||
notifyOnRemove(removeFromWorld);
|
||||
Scene.active.notifyOnInit(function() {
|
||||
notifyOnInit(init);
|
||||
notifyOnLateUpdate(lateUpdate);
|
||||
notifyOnRemove(removeFromWorld);
|
||||
});
|
||||
}
|
||||
|
||||
inline function withMargin(f:Float) {
|
||||
|
|
BIN
blender/data/editor_data.blend
Normal file
BIN
blender/data/editor_data.blend
Normal file
Binary file not shown.
|
@ -21,6 +21,7 @@ from bpy_extras.io_utils import ExportHelper
|
|||
import assets
|
||||
import utils
|
||||
import subprocess
|
||||
import make
|
||||
|
||||
kNodeTypeNode = 0
|
||||
kNodeTypeBone = 1
|
||||
|
@ -1450,7 +1451,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
|
||||
o['material_refs'] = []
|
||||
for i in range(len(bobject.material_slots)):
|
||||
if self.object_has_override_material(bobject): # Overwrite material slot
|
||||
if bobject.override_material: # Overwrite material slot
|
||||
o['material_refs'].append(bobject.override_material_name)
|
||||
else: # Export assigned material
|
||||
self.ExportMaterialRef(bobject.material_slots[i].material, i, o)
|
||||
|
@ -1967,7 +1968,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
om['instance_offsets'] = instance_offsets
|
||||
|
||||
# Export usage
|
||||
om['static_usage'] = self.get_mesh_static_usage(bobject.data)
|
||||
om['dynamic_usage'] = bobject.data.dynamic_usage
|
||||
|
||||
o['mesh'] = om
|
||||
self.write_mesh(bobject, fp, o)
|
||||
|
@ -2149,7 +2150,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
o['lamp_size'] = objref.shadow_soft_size
|
||||
|
||||
# Parse nodes, only emission for now
|
||||
# Merge with nodes_material
|
||||
# Merge with make_material
|
||||
for n in objref.node_tree.nodes:
|
||||
if n.type == 'EMISSION':
|
||||
col = n.inputs[0].default_value
|
||||
|
@ -2230,6 +2231,12 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
o['sound'] = utils.safe_filename(o['sound'])
|
||||
else:
|
||||
o['sound'] = ''
|
||||
o['muted'] = objref.muted
|
||||
o['loop'] = objref.loop
|
||||
o['stream'] = objref.stream
|
||||
o['volume'] = objref.volume
|
||||
o['pitch'] = objref.pitch
|
||||
o['attenuation'] = objref.attenuation
|
||||
self.output['speaker_datas'].append(o)
|
||||
|
||||
def ExportMaterials(self):
|
||||
|
@ -2467,12 +2474,6 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
bobject.data.mesh_cached_verts = len(bobject.data.vertices)
|
||||
bobject.data.mesh_cached_edges = len(bobject.data.edges)
|
||||
|
||||
def object_has_override_material(self, bobject):
|
||||
return bobject.override_material
|
||||
|
||||
def get_mesh_static_usage(self, data):
|
||||
return data.static_usage
|
||||
|
||||
def get_export_tangents(self, mesh):
|
||||
for m in mesh.materials:
|
||||
if m.export_tangents == True:
|
||||
|
@ -2592,7 +2593,10 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
cwd = os.getcwd()
|
||||
os.chdir(scriptspath)
|
||||
# Disable minification for now, too slow
|
||||
subprocess.Popen([python_path + ' ' + sdk_path + '/lib/transcrypt/__main__.py' + ' ' + pyname + ' --nomin'], shell=True)
|
||||
transproc = subprocess.Popen([python_path + ' ' + sdk_path + '/lib/transcrypt/__main__.py' + ' ' + pyname + ' --nomin'], shell=True)
|
||||
transproc.wait()
|
||||
if transproc.poll() != 0:
|
||||
make.armory_log('Compiling ' + pyname + ' failed, check console')
|
||||
os.chdir(cwd)
|
||||
# Compiled file
|
||||
assets.add('build/compiled/scripts/__javascript__/' + t.jsscript_prop + '.js')
|
||||
|
@ -2771,10 +2775,10 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
decal_context = bpy.data.cameras[0].last_decal_context
|
||||
|
||||
# Parse nodes
|
||||
import nodes_material
|
||||
import make_material
|
||||
# Parse from material output
|
||||
if decal_uv_layer == None:
|
||||
nodes_material.parse(self, material, c, defs)
|
||||
make_material.parse(self, material, c, defs)
|
||||
o['contexts'].append(c)
|
||||
# Decal attached, split material into two separate ones
|
||||
# Mandatory starting point from mix node for now
|
||||
|
@ -2788,12 +2792,12 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
c2['bind_textures'] = []
|
||||
defs2 = []
|
||||
tree = material.node_tree
|
||||
output_node = nodes_material.get_output_node(tree)
|
||||
mix_node = nodes_material.find_node_by_link(tree, output_node, output_node.inputs[0])
|
||||
surface_node1 = nodes_material.find_node_by_link(tree, mix_node, mix_node.inputs[1])
|
||||
surface_node2 = nodes_material.find_node_by_link(tree, mix_node, mix_node.inputs[2])
|
||||
nodes_material.parse_from(self, material, c, defs, surface_node1)
|
||||
nodes_material.parse_from(self, material, c2, defs2, surface_node2)
|
||||
output_node = make_material.get_output_node(tree)
|
||||
mix_node = make_material.find_node_by_link(tree, output_node, output_node.inputs[0])
|
||||
surface_node1 = make_material.find_node_by_link(tree, mix_node, mix_node.inputs[1])
|
||||
surface_node2 = make_material.find_node_by_link(tree, mix_node, mix_node.inputs[2])
|
||||
make_material.parse_from(self, material, c, defs, surface_node1)
|
||||
make_material.parse_from(self, material, c2, defs2, surface_node2)
|
||||
o['contexts'].append(c)
|
||||
o2['contexts'].append(c2)
|
||||
self.finalize_shader(o2, defs2, [decal_context])
|
||||
|
@ -2832,7 +2836,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
|
|||
if ob.find_armature() and self.is_bone_animation_enabled(ob) and bpy.data.worlds['Arm'].generate_gpu_skin == True:
|
||||
defs.append('_Skinning')
|
||||
# Billboarding
|
||||
if len(ob.constraints) > 0 and ob.constraints[0].target != None and \
|
||||
if len(ob.constraints) > 0 and ob.constraints[0].type == 'TRACK_TO' and ob.constraints[0].target != None and \
|
||||
ob.constraints[0].target.type == 'CAMERA' and ob.constraints[0].mute == False:
|
||||
defs.append('_Billboard')
|
||||
|
||||
|
|
134
blender/make.py
134
blender/make.py
|
@ -10,9 +10,9 @@ import subprocess
|
|||
import threading
|
||||
import webbrowser
|
||||
import write_data
|
||||
import nodes_logic
|
||||
import nodes_renderpath
|
||||
import nodes_world
|
||||
import make_logic
|
||||
import make_renderpath
|
||||
import make_world
|
||||
import path_tracer
|
||||
from exporter import ArmoryExporter
|
||||
import lib.make_datas
|
||||
|
@ -42,10 +42,10 @@ def init_armory_props():
|
|||
if scene.render.engine != 'CYCLES':
|
||||
scene.render.engine = 'CYCLES'
|
||||
scene.render.fps = 60 # Default to 60fps for update loop
|
||||
# Force camera far to at least 100 units for now, to prevent fighting with light far plane
|
||||
# Force camera far to at least 200 units for now, to prevent fighting with light far plane
|
||||
for c in bpy.data.cameras:
|
||||
if c.clip_end < 100:
|
||||
c.clip_end = 100
|
||||
if c.clip_end < 200:
|
||||
c.clip_end = 200
|
||||
# Use nodes
|
||||
for w in bpy.data.worlds:
|
||||
w.use_nodes = True
|
||||
|
@ -96,15 +96,15 @@ def export_data(fp, sdk_path, is_play=False):
|
|||
|
||||
# Build node trees
|
||||
# TODO: cache
|
||||
nodes_logic.buildNodeTrees()
|
||||
make_logic.buildNodeTrees()
|
||||
active_worlds = set()
|
||||
for scene in bpy.data.scenes:
|
||||
if scene.game_export and scene.world != None and scene.world.name != 'Arm':
|
||||
active_worlds.add(scene.world)
|
||||
world_outputs = nodes_world.buildNodeTrees(active_worlds)
|
||||
linked_assets = nodes_renderpath.buildNodeTrees(shader_references, asset_references, assets_path)
|
||||
world_outputs = make_world.buildNodeTrees(active_worlds)
|
||||
linked_assets = make_renderpath.buildNodeTrees(shader_references, asset_references, assets_path)
|
||||
for wout in world_outputs:
|
||||
nodes_world.write_output(wout, asset_references, shader_references)
|
||||
make_world.write_output(wout, asset_references, shader_references)
|
||||
|
||||
# Export scene data
|
||||
assets.embedded_data = sorted(list(set(assets.embedded_data)))
|
||||
|
@ -166,7 +166,7 @@ def export_data(fp, sdk_path, is_play=False):
|
|||
write_data.write_khafilejs(shader_references, asset_references, is_play, export_physics)
|
||||
|
||||
# Write Main.hx
|
||||
write_data.write_main()
|
||||
write_data.write_main(is_play, play_project.in_viewport)
|
||||
|
||||
# Copy ammo.js if necessary
|
||||
#if target_name == 'html5':
|
||||
|
@ -177,50 +177,39 @@ def export_data(fp, sdk_path, is_play=False):
|
|||
if not os.path.isfile('build/debug-html5/ammo.js'):
|
||||
shutil.copy(ammojs_path, 'build/debug-html5')
|
||||
|
||||
def process_text(text):
|
||||
if text == None:
|
||||
return True
|
||||
# Proof of concept..
|
||||
text = text.split(' ', 1)
|
||||
if len(text) > 1:
|
||||
text = text[1]
|
||||
cmd = text.split('|')
|
||||
# Reflect commands from Armory player in Blender
|
||||
if cmd[0] == '__arm':
|
||||
if cmd[1] == 'setx':
|
||||
bpy.context.scene.objects[cmd[2]].location.x = float(cmd[3])
|
||||
elif cmd[1] == 'select':
|
||||
bpy.context.object.select = False
|
||||
bpy.context.scene.objects[cmd[2]].select = True
|
||||
bpy.context.scene.objects.active = bpy.context.scene.objects[cmd[2]]
|
||||
return False
|
||||
return True
|
||||
|
||||
def armory_log(text=None):
|
||||
if process_text(text):
|
||||
if text == None:
|
||||
text = ''
|
||||
print(text)
|
||||
text = (text[:80] + '..') if len(text) > 80 else text # Limit str size
|
||||
ArmoryProjectPanel.info_text = text
|
||||
armory_log.tag_redraw = True
|
||||
if text == None:
|
||||
text = ''
|
||||
print(text)
|
||||
text = (text[:80] + '..') if len(text) > 80 else text # Limit str size
|
||||
ArmoryProjectPanel.info_text = text
|
||||
armory_log.tag_redraw = True
|
||||
armory_log.tag_redraw = False
|
||||
|
||||
def armory_space_log(text):
|
||||
if process_text(text):
|
||||
print(text)
|
||||
text = (text[:80] + '..') if len(text) > 80 else text # Limit str size
|
||||
space_armory.SPACEARMORY_HT_header.info_text = text
|
||||
def armory_progress(value):
|
||||
ArmoryProjectPanel.progress = value
|
||||
armory_log.tag_redraw = True
|
||||
|
||||
def armory_space_log(text=None):
|
||||
if text == None:
|
||||
text = ''
|
||||
print(text)
|
||||
text = (text[:80] + '..') if len(text) > 80 else text # Limit str size
|
||||
space_armory.SPACEARMORY_HT_header.info_text = text
|
||||
|
||||
def get_kha_target(target_name): # TODO: remove
|
||||
if target_name == 'macos':
|
||||
return 'osx'
|
||||
return target_name
|
||||
|
||||
def compile_project(target_name=None, is_publish=False):
|
||||
def compile_project(target_name=None, is_publish=False, watch=False):
|
||||
user_preferences = bpy.context.user_preferences
|
||||
addon_prefs = user_preferences.addons['armory'].preferences
|
||||
sdk_path = addon_prefs.sdk_path
|
||||
ffmpeg_path = addon_prefs.ffmpeg_path
|
||||
|
||||
# Prevent launching the player after compile process finishes
|
||||
make.play_project.in_viewport = False
|
||||
|
||||
# Set build command
|
||||
if target_name == None:
|
||||
|
@ -239,12 +228,16 @@ def compile_project(target_name=None, is_publish=False):
|
|||
kha_target_name = get_kha_target(target_name)
|
||||
cmd = [node_path, khamake_path, kha_target_name, '--glsl2']
|
||||
|
||||
if ffmpeg_path != '':
|
||||
cmd.append('--ffmpeg')
|
||||
cmd.append('"' + ffmpeg_path + '"')
|
||||
|
||||
# armory_log("Building, see console...")
|
||||
|
||||
if make.play_project.playproc != None or make.play_project.chromium_running:
|
||||
if make.play_project.chromium_running:
|
||||
if play_project.compileproc == None: # Already compiling
|
||||
# Patch running game, stay silent, disable krafix and haxe
|
||||
cmd.append('--silent')
|
||||
# cmd.append('--silent')
|
||||
cmd.append('--noproject')
|
||||
cmd.append('--haxe')
|
||||
cmd.append('""')
|
||||
|
@ -254,8 +247,10 @@ def compile_project(target_name=None, is_publish=False):
|
|||
play_project.compileproc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
|
||||
threading.Timer(0.1, watch_patch).start()
|
||||
return play_project.compileproc
|
||||
else:
|
||||
return None
|
||||
elif watch == True:
|
||||
play_project.compileproc = subprocess.Popen(cmd)
|
||||
threading.Timer(0.1, watch_compile, ['build']).start()
|
||||
return play_project.compileproc
|
||||
else:
|
||||
return subprocess.Popen(cmd)
|
||||
|
||||
|
@ -272,6 +267,11 @@ def build_project(is_play=False):
|
|||
# Save blend
|
||||
bpy.ops.wm.save_mainfile()
|
||||
|
||||
# Clean log
|
||||
armory_log()
|
||||
if utils.with_chromium():
|
||||
armory_space_log()
|
||||
|
||||
# Set camera in active scene
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
active_scene = bpy.context.screen.scene if wrd.ArmPlayActiveScene else bpy.data.scenes[wrd.ArmProjectScene]
|
||||
|
@ -330,6 +330,9 @@ def build_project(is_play=False):
|
|||
# Export data
|
||||
export_data(fp, sdk_path, is_play=is_play)
|
||||
|
||||
if play_project.playproc == None:
|
||||
armory_progress(50)
|
||||
|
||||
def stop_project():
|
||||
if play_project.playproc != None:
|
||||
play_project.playproc.terminate()
|
||||
|
@ -353,15 +356,17 @@ def watch_play():
|
|||
play_project.playproc_finished = True
|
||||
armory_log()
|
||||
|
||||
def watch_compile(is_publish=False):
|
||||
def watch_compile(mode):
|
||||
print('WATCHHHH', mode)
|
||||
play_project.compileproc.wait()
|
||||
result = play_project.compileproc.poll()
|
||||
play_project.compileproc = None
|
||||
play_project.compileproc_finished = True
|
||||
if result == 0:
|
||||
on_compiled(is_publish)
|
||||
on_compiled(mode)
|
||||
else:
|
||||
armory_log('Build failed, check console')
|
||||
armory_progress(100)
|
||||
|
||||
def watch_patch():
|
||||
play_project.compileproc.wait()
|
||||
|
@ -415,7 +420,7 @@ def play_project(self, in_viewport):
|
|||
|
||||
# Compile
|
||||
play_project.compileproc = compile_project(target_name='html5')
|
||||
threading.Timer(0.1, watch_compile).start()
|
||||
threading.Timer(0.1, watch_compile, ['play']).start()
|
||||
|
||||
play_project.in_viewport = False
|
||||
play_project.playproc = None
|
||||
|
@ -424,6 +429,7 @@ play_project.playproc_finished = False
|
|||
play_project.compileproc_finished = False
|
||||
play_project.play_area = None
|
||||
play_project.chromium_running = False
|
||||
play_project.last_chromium_running = False
|
||||
|
||||
def run_server():
|
||||
Handler = http.server.SimpleHTTPRequestHandler
|
||||
|
@ -433,14 +439,15 @@ def run_server():
|
|||
except:
|
||||
print('Server already running')
|
||||
|
||||
def on_compiled(is_publish=False):
|
||||
def on_compiled(mode): # build, play, publish
|
||||
armory_progress(100)
|
||||
armory_log()
|
||||
user_preferences = bpy.context.user_preferences
|
||||
addon_prefs = user_preferences.addons['armory'].preferences
|
||||
sdk_path = addon_prefs.sdk_path
|
||||
|
||||
# Print info
|
||||
if is_publish:
|
||||
if mode == 'publish':
|
||||
target_name = get_kha_target(bpy.data.worlds['Arm'].ArmPublishTarget)
|
||||
print('Project published')
|
||||
files_path = utils.get_fp() + '/build/' + target_name
|
||||
|
@ -457,7 +464,7 @@ def on_compiled(is_publish=False):
|
|||
return
|
||||
|
||||
# Otherwise launch project
|
||||
if utils.with_chromium() == False or play_project.in_viewport == False:
|
||||
elif mode =='play' and (utils.with_chromium() == False or play_project.in_viewport == False):
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
if wrd.ArmPlayRuntime == 'Electron':
|
||||
electron_app_path = './build/electron.js'
|
||||
|
@ -485,12 +492,25 @@ def on_compiled(is_publish=False):
|
|||
def clean_project():
|
||||
os.chdir(utils.get_fp())
|
||||
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
|
||||
# Preserve envmaps
|
||||
if not wrd.ArmCleanEnvmaps:
|
||||
envmaps_path = 'build/compiled/Assets/envmaps'
|
||||
if os.path.isdir(envmaps_path):
|
||||
shutil.move(envmaps_path, '.')
|
||||
|
||||
# Remove build and compiled data
|
||||
if os.path.isdir('build'):
|
||||
shutil.rmtree('build')
|
||||
|
||||
# Move envmaps back
|
||||
if not wrd.ArmCleanEnvmaps and os.path.isdir('envmaps'):
|
||||
os.makedirs('build/compiled/Assets')
|
||||
shutil.move('envmaps', 'build/compiled/Assets')
|
||||
|
||||
# Remove compiled nodes
|
||||
nodes_path = 'Sources/' + bpy.data.worlds['Arm'].ArmProjectPackage.replace('.', '/') + '/node/'
|
||||
nodes_path = 'Sources/' + wrd.ArmProjectPackage.replace('.', '/') + '/node/'
|
||||
if os.path.isdir(nodes_path):
|
||||
shutil.rmtree(nodes_path)
|
||||
|
||||
|
@ -505,10 +525,14 @@ def clean_project():
|
|||
print('Project cleaned')
|
||||
|
||||
def publish_project():
|
||||
# Force minimize data
|
||||
minimize = bpy.data.worlds['Arm'].ArmMinimize
|
||||
bpy.data.worlds['Arm'].ArmMinimize = True
|
||||
clean_project()
|
||||
build_project()
|
||||
play_project.compileproc = compile_project(target_name=bpy.data.worlds['Arm'].ArmPublishTarget, is_publish=True)
|
||||
threading.Timer(0.1, watch_compile, {"is_publish" : True}).start()
|
||||
threading.Timer(0.1, watch_compile, ['publish']).start()
|
||||
bpy.data.worlds['Arm'].ArmMinimize = minimize
|
||||
|
||||
# Registration
|
||||
def register():
|
||||
|
|
|
@ -5,14 +5,6 @@ import os
|
|||
import json
|
||||
import write_probes
|
||||
|
||||
def register():
|
||||
pass
|
||||
#bpy.utils.register_module(__name__)
|
||||
|
||||
def unregister():
|
||||
pass
|
||||
#bpy.utils.unregister_module(__name__)
|
||||
|
||||
def parse_defs(node_group):
|
||||
|
||||
rn = get_root_node(node_group)
|
||||
|
@ -87,3 +79,11 @@ def get_output_node(node_group, from_node, output_index):
|
|||
if link.to_node.bl_idname == 'NodeReroute': # Step through reroutes
|
||||
return findNodeByLinkFrom(node_group, link.to_node, link.to_node.inputs[0])
|
||||
return link.to_node
|
||||
|
||||
def register():
|
||||
pass
|
||||
#bpy.utils.register_module(__name__)
|
||||
|
||||
def unregister():
|
||||
pass
|
||||
#bpy.utils.unregister_module(__name__)
|
111
blender/make_logic.py
Executable file
111
blender/make_logic.py
Executable file
|
@ -0,0 +1,111 @@
|
|||
import bpy
|
||||
from bpy.types import NodeTree, Node, NodeSocket
|
||||
from bpy.props import *
|
||||
import os
|
||||
import sys
|
||||
import nodes_logic
|
||||
|
||||
# Generating node sources
|
||||
def buildNodeTrees():
|
||||
s = bpy.data.filepath.split(os.path.sep)
|
||||
s.pop()
|
||||
fp = os.path.sep.join(s)
|
||||
os.chdir(fp)
|
||||
|
||||
# Make sure package dir exists
|
||||
nodes_path = 'Sources/' + bpy.data.worlds['Arm'].ArmProjectPackage.replace(".", "/") + "/node"
|
||||
if not os.path.exists(nodes_path):
|
||||
os.makedirs(nodes_path)
|
||||
|
||||
# Export node scripts
|
||||
for node_group in bpy.data.node_groups:
|
||||
if node_group.bl_idname == 'ArmLogicTreeType': # Build only game trees
|
||||
node_group.use_fake_user = True # Keep fake references for now
|
||||
buildNodeTree(node_group)
|
||||
|
||||
def buildNodeTree(node_group):
|
||||
path = 'Sources/' + bpy.data.worlds['Arm'].ArmProjectPackage.replace('.', '/') + '/node/'
|
||||
node_group_name = node_group.name.replace('.', '_').replace(' ', '')
|
||||
|
||||
with open(path + node_group_name + '.hx', 'w') as f:
|
||||
f.write('package ' + bpy.data.worlds['Arm'].ArmProjectPackage + '.node;\n\n')
|
||||
f.write('import armory.logicnode.*;\n\n')
|
||||
f.write('class ' + node_group_name + ' extends armory.trait.internal.NodeExecutor {\n\n')
|
||||
f.write('\tpublic function new() { super(); notifyOnAdd(add); }\n\n')
|
||||
f.write('\tfunction add() {\n')
|
||||
# Make sure root node exists
|
||||
roots = get_root_nodes(node_group)
|
||||
created_nodes = []
|
||||
for rn in roots:
|
||||
name = '_' + rn.name.replace('.', '_').replace(' ', '')
|
||||
buildNode(node_group, rn, f, created_nodes)
|
||||
f.write('\n\t\tstart(' + name + ');\n\n')
|
||||
f.write('\t}\n')
|
||||
f.write('}\n')
|
||||
|
||||
def buildNode(node_group, node, f, created_nodes):
|
||||
# Get node name
|
||||
name = '_' + node.name.replace('.', '_').replace(' ', '')
|
||||
|
||||
# Check if node already exists
|
||||
for n in created_nodes:
|
||||
if n == name:
|
||||
return name
|
||||
|
||||
# Create node
|
||||
type = node.name.split(".")[0].replace(' ', '') + "Node"
|
||||
f.write('\t\tvar ' + name + ' = new ' + type + '();\n')
|
||||
created_nodes.append(name)
|
||||
|
||||
# Properties
|
||||
if hasattr(node, "property0"):
|
||||
f.write('\t\t' + name + '.property0 = "' + node.property0 + '";\n')
|
||||
if hasattr(node, "property1"):
|
||||
f.write('\t\t' + name + '.property1 = "' + node.property1 + '";\n')
|
||||
if hasattr(node, "property2"):
|
||||
f.write('\t\t' + name + '.property2 = "' + node.property2 + '";\n')
|
||||
if hasattr(node, "property3"):
|
||||
f.write('\t\t' + name + '.property3 = "' + node.property3 + '";\n')
|
||||
if hasattr(node, "property4"):
|
||||
f.write('\t\t' + name + '.property4 = "' + node.property4 + '";\n')
|
||||
|
||||
# Create inputs
|
||||
for inp in node.inputs:
|
||||
# Is linked - find node
|
||||
inpname = ''
|
||||
if inp.is_linked:
|
||||
n = findNodeByLink(node_group, node, inp)
|
||||
inpname = buildNode(node_group, n, f, created_nodes)
|
||||
# Not linked - create node with default values
|
||||
else:
|
||||
inpname = build_default_node(inp)
|
||||
|
||||
# Add input
|
||||
f.write('\t\t' + name + '.inputs.push(' + inpname + ');\n')
|
||||
|
||||
return name
|
||||
|
||||
def findNodeByLink(node_group, to_node, inp):
|
||||
for link in node_group.links:
|
||||
if link.to_node == to_node and link.to_socket == inp:
|
||||
if link.from_node.bl_idname == 'NodeReroute': # Step through reroutes
|
||||
return findNodeByLink(node_group, link.from_node, link.from_node.inputs[0])
|
||||
return link.from_node
|
||||
|
||||
def get_root_nodes(node_group):
|
||||
roots = []
|
||||
for n in node_group.nodes:
|
||||
if len(n.outputs) == 0: # Assume node with no outputs as roots
|
||||
roots.append(n)
|
||||
return roots
|
||||
|
||||
def build_default_node(inp):
|
||||
inpname = ''
|
||||
if inp.type == "VECTOR":
|
||||
inpname = 'VectorNode.create(' + str(inp.default_value[0]) + ', ' + str(inp.default_value[1]) + ", " + str(inp.default_value[2]) + ')'
|
||||
elif inp.type == "VALUE":
|
||||
inpname = 'FloatNode.create(' + str(inp.default_value) + ')'
|
||||
elif inp.type == 'BOOLEAN':
|
||||
inpname = 'BoolNode.create(' + str(inp.default_value).lower() + ')'
|
||||
|
||||
return inpname
|
816
blender/make_renderpath.py
Executable file
816
blender/make_renderpath.py
Executable file
|
@ -0,0 +1,816 @@
|
|||
import bpy
|
||||
from bpy.types import NodeTree, Node, NodeSocket
|
||||
from bpy.props import *
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import platform
|
||||
import subprocess
|
||||
import make_compositor
|
||||
from utils import to_hex
|
||||
import assets
|
||||
import utils
|
||||
|
||||
# Handling node data
|
||||
def reload_blend_data():
|
||||
if bpy.data.node_groups.get('forward_path') == None:
|
||||
load_library()
|
||||
pass
|
||||
|
||||
def load_library():
|
||||
user_preferences = bpy.context.user_preferences
|
||||
addon_prefs = user_preferences.addons['armory'].preferences
|
||||
sdk_path = addon_prefs.sdk_path
|
||||
data_path = sdk_path + '/armory/blender/data/data.blend'
|
||||
|
||||
with bpy.data.libraries.load(data_path, link=False) as (data_from, data_to):
|
||||
data_to.node_groups = ['forward_path', 'forward_path_low', 'deferred_path', 'deferred_path_low', 'deferred_path_high', 'hybrid_path', 'vr_path', 'pathtrace_path', 'Armory PBR']
|
||||
|
||||
# TODO: cannot use for loop
|
||||
bpy.data.node_groups['forward_path'].use_fake_user = True
|
||||
bpy.data.node_groups['forward_path_low'].use_fake_user = True
|
||||
bpy.data.node_groups['deferred_path'].use_fake_user = True
|
||||
bpy.data.node_groups['deferred_path_low'].use_fake_user = True
|
||||
bpy.data.node_groups['deferred_path_high'].use_fake_user = True
|
||||
bpy.data.node_groups['hybrid_path'].use_fake_user = True
|
||||
bpy.data.node_groups['vr_path'].use_fake_user = True
|
||||
bpy.data.node_groups['pathtrace_path'].use_fake_user = True
|
||||
bpy.data.node_groups['Armory PBR'].use_fake_user = True
|
||||
|
||||
def buildNodeTrees(shader_references, asset_references, assets_path):
|
||||
s = bpy.data.filepath.split(os.path.sep)
|
||||
s.pop()
|
||||
fp = os.path.sep.join(s)
|
||||
os.chdir(fp)
|
||||
|
||||
# Make sure Assets dir exists
|
||||
if not os.path.exists('build/compiled/Assets/renderpaths'):
|
||||
os.makedirs('build/compiled/Assets/renderpaths')
|
||||
|
||||
buildNodeTrees.assets_path = assets_path
|
||||
buildNodeTrees.linked_assets = []
|
||||
# Always include
|
||||
buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'brdf.png')
|
||||
|
||||
# Export render path for each camera
|
||||
parsed_paths = []
|
||||
for cam in bpy.data.cameras:
|
||||
# if cam.game_export
|
||||
if cam.renderpath_path not in parsed_paths:
|
||||
node_group = bpy.data.node_groups[cam.renderpath_path]
|
||||
buildNodeTree(cam, node_group, shader_references, asset_references)
|
||||
parsed_paths.append(cam.renderpath_path)
|
||||
|
||||
return buildNodeTrees.linked_assets
|
||||
|
||||
def buildNodeTree(cam, node_group, shader_references, asset_references):
|
||||
buildNodeTree.cam = cam
|
||||
output = {}
|
||||
dat = {}
|
||||
output['renderpath_datas'] = [dat]
|
||||
|
||||
path = 'build/compiled/Assets/renderpaths/'
|
||||
node_group_name = node_group.name.replace('.', '_')
|
||||
|
||||
rn = get_root_node(node_group)
|
||||
if rn == None:
|
||||
return
|
||||
|
||||
dat['name'] = node_group_name
|
||||
|
||||
# Store main context names
|
||||
dat['mesh_context'] = buildNodeTree.cam.mesh_context
|
||||
dat['shadows_context'] = buildNodeTree.cam.shadows_context
|
||||
|
||||
dat['render_targets'], dat['depth_buffers'] = preprocess_renderpath(rn, node_group)
|
||||
dat['stages'] = []
|
||||
|
||||
buildNode(dat['stages'], rn, node_group, shader_references, asset_references)
|
||||
|
||||
asset_path = path + node_group_name + '.arm'
|
||||
utils.write_arm(asset_path, output)
|
||||
assets.add(asset_path)
|
||||
|
||||
def make_set_target(stage, node_group, node, currentNode=None, target_index=1, viewport_scale=1.0):
|
||||
if currentNode == None:
|
||||
currentNode = node
|
||||
|
||||
stage['command'] = 'set_target'
|
||||
|
||||
# First param is viewport scale
|
||||
if len(stage['params']) == 0:
|
||||
stage['params'].append(viewport_scale)
|
||||
|
||||
currentNode = findNodeByLink(node_group, currentNode, currentNode.inputs[target_index])
|
||||
|
||||
if currentNode.bl_idname == 'TargetNodeType':
|
||||
targetId = currentNode.inputs[0].default_value
|
||||
stage['params'].append(targetId)
|
||||
# Store current target size
|
||||
buildNode.last_set_target_w = currentNode.inputs[1].default_value
|
||||
buildNode.last_set_target_h = currentNode.inputs[2].default_value
|
||||
|
||||
elif currentNode.bl_idname == 'GBufferNodeType':
|
||||
# Set all linked targets
|
||||
for i in range(0, 5):
|
||||
if currentNode.inputs[i].is_linked:
|
||||
make_set_target(stage, node_group, node, currentNode, target_index=i)
|
||||
|
||||
elif currentNode.bl_idname == 'NodeReroute':
|
||||
make_set_target(stage, node_group, node, currentNode, target_index=0)
|
||||
|
||||
else: # Framebuffer
|
||||
targetId = ''
|
||||
stage['params'].append(targetId)
|
||||
|
||||
def make_clear_target(stage, color_val=None, depth_val=None, stencil_val=None):
|
||||
stage['command'] = 'clear_target'
|
||||
if color_val != None:
|
||||
stage['params'].append('color')
|
||||
if color_val == -1: # Clear to world background color
|
||||
stage['params'].append('-1')
|
||||
else:
|
||||
stage['params'].append(str(to_hex(color_val)))
|
||||
if depth_val != None:
|
||||
stage['params'].append('depth')
|
||||
stage['params'].append(str(depth_val))
|
||||
if stencil_val != None:
|
||||
stage['params'].append('stencil')
|
||||
stage['params'].append(str(stencil_val))
|
||||
|
||||
def make_draw_meshes(stage, node_group, node):
|
||||
stage['command'] = 'draw_meshes'
|
||||
# Context
|
||||
context = node.inputs[1].default_value
|
||||
# Store shadowmap size
|
||||
if context == buildNodeTree.cam.shadows_context:
|
||||
bpy.data.worlds['Arm'].shadowmap_size = buildNode.last_set_target_w
|
||||
stage['params'].append(context)
|
||||
# Order
|
||||
order = node.inputs[2].default_value
|
||||
stage['params'].append(order)
|
||||
|
||||
def make_draw_decals(stage, node_group, node, shader_references, asset_references):
|
||||
stage['command'] = 'draw_decals'
|
||||
context = node.inputs[1].default_value
|
||||
stage['params'].append(context) # Context
|
||||
buildNodeTree.cam.last_decal_context = context
|
||||
|
||||
def make_bind_target(stage, node_group, node, constant_name, currentNode=None, target_index=1):
|
||||
if currentNode == None:
|
||||
currentNode = node
|
||||
|
||||
stage['command'] = 'bind_target'
|
||||
|
||||
link = findLink(node_group, currentNode, currentNode.inputs[target_index])
|
||||
currentNode = link.from_node
|
||||
|
||||
if currentNode.bl_idname == 'NodeReroute':
|
||||
make_bind_target(stage, node_group, node, constant_name, currentNode=currentNode, target_index=0)
|
||||
|
||||
elif currentNode.bl_idname == 'GBufferNodeType':
|
||||
for i in range(0, 5):
|
||||
if currentNode.inputs[i].is_linked:
|
||||
targetNode = findNodeByLink(node_group, currentNode, currentNode.inputs[i])
|
||||
targetId = targetNode.inputs[0].default_value
|
||||
# if i == 0 and targetNode.inputs[3].default_value == True: # Depth
|
||||
if targetNode.inputs[3].is_linked: # Depth
|
||||
db_node = findNodeByLink(node_group, targetNode, targetNode.inputs[3])
|
||||
db_id = db_node.inputs[0].default_value
|
||||
stage['params'].append('_' + db_id)
|
||||
stage['params'].append(constant_name + 'D')
|
||||
stage['params'].append(targetId) # Color buffer
|
||||
stage['params'].append(constant_name + str(i))
|
||||
|
||||
elif currentNode.bl_idname == 'TargetNodeType':
|
||||
targetId = currentNode.inputs[0].default_value
|
||||
stage['params'].append(targetId)
|
||||
stage['params'].append(constant_name)
|
||||
|
||||
elif currentNode.bl_idname == 'DepthBufferNodeType':
|
||||
targetId = '_' + currentNode.inputs[0].default_value
|
||||
stage['params'].append(targetId)
|
||||
stage['params'].append(constant_name)
|
||||
|
||||
def make_draw_material_quad(stage, node_group, node, shader_references, asset_references, context_index=1):
|
||||
stage['command'] = 'draw_material_quad'
|
||||
material_context = node.inputs[context_index].default_value
|
||||
stage['params'].append(material_context)
|
||||
# Include data and shaders
|
||||
shader_context = node.inputs[context_index].default_value
|
||||
scon = shader_context.split('/')
|
||||
dir_name = scon[2]
|
||||
# No world defs for material passes
|
||||
data_name = scon[2]
|
||||
asset_references.append('build/compiled/ShaderDatas/' + dir_name + '/' + data_name + '.arm')
|
||||
shader_references.append('build/compiled/Shaders/' + dir_name + '/' + data_name)
|
||||
|
||||
def make_draw_quad(stage, node_group, node, shader_references, asset_references, context_index=1, shader_context=None):
|
||||
stage['command'] = 'draw_shader_quad'
|
||||
# Append world defs to get proper context
|
||||
world_defs = bpy.data.worlds['Arm'].world_defs
|
||||
if shader_context == None:
|
||||
shader_context = node.inputs[context_index].default_value
|
||||
scon = shader_context.split('/')
|
||||
stage['params'].append(scon[0] + world_defs + '/' + scon[1] + world_defs + '/' + scon[2])
|
||||
# Include data and shaders
|
||||
dir_name = scon[0]
|
||||
# Append world defs
|
||||
data_name = scon[1] + world_defs
|
||||
asset_references.append('build/compiled/ShaderDatas/' + dir_name + '/' + data_name + '.arm')
|
||||
shader_references.append('build/compiled/Shaders/' + dir_name + '/' + data_name)
|
||||
|
||||
def make_draw_world(stage, node_group, node, shader_references, asset_references, dome=True):
|
||||
if dome:
|
||||
stage['command'] = 'draw_skydome'
|
||||
else:
|
||||
stage['command'] = 'draw_material_quad'
|
||||
# stage['params'].append(wname + '_material/' + wname + '_material/env')
|
||||
stage['params'].append('_worldMaterial') # Link to active world
|
||||
# Link assets
|
||||
if '_EnvClouds' in bpy.data.worlds['Arm'].world_defs:
|
||||
buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'noise256.png')
|
||||
assets.add_embedded_data('noise256.png')
|
||||
|
||||
def make_draw_compositor(stage, node_group, node, shader_references, asset_references, with_fxaa=False):
|
||||
scon = 'compositor_pass'
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
world_defs = wrd.world_defs
|
||||
compositor_defs = make_compositor.parse_defs(bpy.data.scenes[0].node_tree) # Thrown in scene 0 for now
|
||||
# Additional compositor flags
|
||||
compo_depth = False # Read depth
|
||||
compo_pos = False # Construct position from depth
|
||||
if with_fxaa: # FXAA directly in compositor, useful for forward path
|
||||
compositor_defs += '_CompoFXAA'
|
||||
if wrd.generate_letterbox:
|
||||
compositor_defs += '_CompoLetterbox'
|
||||
if wrd.generate_grain:
|
||||
compositor_defs += '_CompoGrain'
|
||||
if bpy.data.scenes[0].cycles.film_exposure != 1.0:
|
||||
compositor_defs += '_CompoExposure'
|
||||
if wrd.generate_fog:
|
||||
compositor_defs += '_CompoFog'
|
||||
compo_pos = True
|
||||
if buildNodeTree.cam.cycles.aperture_size > 0.0:
|
||||
compositor_defs += '_CompoDOF'
|
||||
compo_depth = True
|
||||
if compo_pos:
|
||||
compositor_defs += '_CompoPos'
|
||||
compo_depth = True
|
||||
if compo_depth:
|
||||
compositor_defs += '_CompoDepth'
|
||||
|
||||
defs = world_defs + compositor_defs
|
||||
data_name = scon + defs
|
||||
|
||||
stage['command'] = 'draw_shader_quad'
|
||||
stage['params'].append(data_name + '/' + data_name + '/' + scon)
|
||||
# Include data and shaders
|
||||
asset_references.append('build/compiled/ShaderDatas/' + scon + '/' + data_name + '.arm')
|
||||
shader_references.append('build/compiled/Shaders/' + scon + '/' + data_name)
|
||||
# Link assets
|
||||
# buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'noise256.png')
|
||||
# assets.add_embedded_data('noise256.png')
|
||||
|
||||
def make_call_function(stage, node_group, node):
|
||||
stage['command'] = 'call_function'
|
||||
stage['params'].append(node.inputs[1].default_value)
|
||||
|
||||
def make_branch_function(stage, node_group, node):
|
||||
make_call_function(stage, node_group, node)
|
||||
|
||||
def process_call_function(stage, stages, node, node_group, shader_references, asset_references):
|
||||
# Step till merge node
|
||||
stage['returns_true'] = []
|
||||
if node.outputs[0].is_linked:
|
||||
stageNode = findNodeByLinkFrom(node_group, node, node.outputs[0])
|
||||
buildNode(stage['returns_true'], stageNode, node_group, shader_references, asset_references)
|
||||
|
||||
stage['returns_false'] = []
|
||||
if node.outputs[1].is_linked:
|
||||
stageNode = findNodeByLinkFrom(node_group, node, node.outputs[1])
|
||||
margeNode = buildNode(stage['returns_false'], stageNode, node_group, shader_references, asset_references)
|
||||
|
||||
# Continue using top level stages after merge node
|
||||
afterMergeNode = findNodeByLinkFrom(node_group, margeNode, margeNode.outputs[0])
|
||||
buildNode(stages, afterMergeNode, node_group, shader_references, asset_references)
|
||||
|
||||
def make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[3, 5, 7], bind_target_constants=None, shader_context=None, viewport_scale=1.0, with_clear=False):
|
||||
# Set target
|
||||
if target_index != None and node.inputs[target_index].is_linked:
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
make_set_target(stage, node_group, node, target_index=target_index, viewport_scale=viewport_scale)
|
||||
stages.append(stage)
|
||||
# Optinal clear
|
||||
if with_clear:
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
make_clear_target(stage, color_val=[0.0, 0.0, 0.0, 1.0])
|
||||
stages.append(stage)
|
||||
# Bind targets
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
buildNode.last_bind_target = stage
|
||||
bind_target_used = False
|
||||
for i in range(0, len(bind_target_indices)):
|
||||
index = bind_target_indices[i]
|
||||
if node.inputs[index].is_linked:
|
||||
bind_target_used = True
|
||||
if bind_target_constants == None:
|
||||
constant_name = node.inputs[index + 1].default_value
|
||||
else:
|
||||
constant_name = bind_target_constants[i]
|
||||
make_bind_target(stage, node_group, node, constant_name, target_index=index)
|
||||
if bind_target_used:
|
||||
stages.append(stage)
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
# Draw quad
|
||||
make_draw_quad(stage, node_group, node, shader_references, asset_references, context_index=2, shader_context=shader_context)
|
||||
stages.append(stage)
|
||||
|
||||
def make_ssao_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[3, 4], bind_target_constants=['gbufferD', 'gbuffer0'], shader_context='ssao_pass/ssao_pass/ssao_pass', viewport_scale=bpy.data.worlds['Arm'].generate_ssao_texture_scale)
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=2, bind_target_indices=[1, 4], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_edge_pass/blur_edge_pass/blur_edge_pass_x', viewport_scale=bpy.data.worlds['Arm'].generate_ssao_texture_scale)
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 4], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_edge_pass/blur_edge_pass/blur_edge_pass_y')
|
||||
buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'noise8.png')
|
||||
assets.add_embedded_data('noise8.png')
|
||||
|
||||
def make_ssao_reproject_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[3, 4, 2, 5], bind_target_constants=['gbufferD', 'gbuffer0', 'slast', 'sveloc'], shader_context='ssao_reproject_pass/ssao_reproject_pass/ssao_reproject_pass')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=2, bind_target_indices=[1, 4], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_edge_pass/blur_edge_pass/blur_edge_pass_x')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 4], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_edge_pass/blur_edge_pass/blur_edge_pass_y')
|
||||
buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'noise8.png')
|
||||
assets.add_embedded_data('noise8.png')
|
||||
|
||||
def make_apply_ssao_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=2, bind_target_indices=[4, 5], bind_target_constants=['gbufferD', 'gbuffer0'], shader_context='ssao_pass/ssao_pass/ssao_pass')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=3, bind_target_indices=[2, 5], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_edge_pass/blur_edge_pass/blur_edge_pass_x')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[3, 5], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_edge_pass/blur_edge_pass/blur_edge_pass_y_blend')
|
||||
buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'noise8.png')
|
||||
assets.add_embedded_data('noise8.png')
|
||||
|
||||
def make_ssr_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=2, bind_target_indices=[4, 5, 6], bind_target_constants=['tex', 'gbufferD', 'gbuffer0'], shader_context='ssr_pass/ssr_pass/ssr_pass', viewport_scale=bpy.data.worlds['Arm'].generate_ssr_texture_scale)
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=3, bind_target_indices=[2, 6], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_adaptive_pass/blur_adaptive_pass/blur_adaptive_pass_x', viewport_scale=bpy.data.worlds['Arm'].generate_ssr_texture_scale, with_clear=True) # Have to clear to prevent artefacts, potentially because of viewport scale
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[3, 6], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_adaptive_pass/blur_adaptive_pass/blur_adaptive_pass_y3_blend')
|
||||
|
||||
def make_bloom_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=2, bind_target_indices=[4], bind_target_constants=['tex'], shader_context='bloom_pass/bloom_pass/bloom_pass')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=3, bind_target_indices=[2], bind_target_constants=['tex'], shader_context='blur_gaus_pass/blur_gaus_pass/blur_gaus_pass_x')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[3], bind_target_constants=['tex'], shader_context='blur_gaus_pass/blur_gaus_pass/blur_gaus_pass_y_blend')
|
||||
|
||||
def make_motion_blur_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 3, 4], bind_target_constants=['tex', 'gbufferD', 'gbuffer0'], shader_context='motion_blur_pass/motion_blur_pass/motion_blur_pass')
|
||||
|
||||
def make_motion_blur_velocity_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 3, 4], bind_target_constants=['tex', 'gbuffer0', 'sveloc'], shader_context='motion_blur_veloc_pass/motion_blur_veloc_pass/motion_blur_veloc_pass')
|
||||
|
||||
def make_copy_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2], bind_target_constants=['tex'], shader_context='copy_pass/copy_pass/copy_pass')
|
||||
|
||||
def make_blend_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2], bind_target_constants=['tex'], shader_context='blend_pass/blend_pass/blend_pass')
|
||||
|
||||
def make_combine_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['tex', 'tex2'], shader_context='combine_pass/combine_pass/combine_pass')
|
||||
|
||||
def make_blur_basic_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=2, bind_target_indices=[1], bind_target_constants=['tex'], shader_context='blur_pass/blur_pass/blur_pass_x')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2], bind_target_constants=['tex'], shader_context='blur_pass/blur_pass/blur_pass_y')
|
||||
|
||||
def make_debug_normals_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2], bind_target_constants=['tex'], shader_context='debug_normals_pass/debug_normals_pass/debug_normals_pass')
|
||||
|
||||
def make_fxaa_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2], bind_target_constants=['tex'], shader_context='fxaa_pass/fxaa_pass/fxaa_pass')
|
||||
|
||||
def make_smaa_pass(stages, node_group, node, shader_references, asset_references):
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
make_set_target(stage, node_group, node, target_index=2)
|
||||
stages.append(stage)
|
||||
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
make_clear_target(stage, color_val=[0.0, 0.0, 0.0, 0.0])
|
||||
stages.append(stage)
|
||||
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=None, bind_target_indices=[4], bind_target_constants=['colorTex'], shader_context='smaa_edge_detect/smaa_edge_detect/smaa_edge_detect')
|
||||
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
make_set_target(stage, node_group, node, target_index=3)
|
||||
stages.append(stage)
|
||||
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
make_clear_target(stage, color_val=[0.0, 0.0, 0.0, 0.0])
|
||||
stages.append(stage)
|
||||
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=None, bind_target_indices=[2], bind_target_constants=['edgesTex'], shader_context='smaa_blend_weight/smaa_blend_weight/smaa_blend_weight')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[4, 3, 5], bind_target_constants=['colorTex', 'blendTex', 'sveloc'], shader_context='smaa_neighborhood_blend/smaa_neighborhood_blend/smaa_neighborhood_blend')
|
||||
buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'smaa_area.png')
|
||||
buildNodeTrees.linked_assets.append(buildNodeTrees.assets_path + 'smaa_search.png')
|
||||
assets.add_embedded_data('smaa_area.png')
|
||||
assets.add_embedded_data('smaa_search.png')
|
||||
|
||||
def make_taa_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 3, 4], bind_target_constants=['tex', 'tex2', 'sveloc'], shader_context='taa_pass/taa_pass/taa_pass')
|
||||
|
||||
def make_sss_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[3, 4, 5], bind_target_constants=['tex', 'gbufferD', 'gbuffer0'], shader_context='sss_pass/sss_pass/sss_pass_x')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=2, bind_target_indices=[3, 4, 5], bind_target_constants=['tex', 'gbufferD', 'gbuffer0'], shader_context='sss_pass/sss_pass/sss_pass_y')
|
||||
|
||||
def make_water_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['tex', 'gbufferD'], shader_context='water_pass/water_pass/water_pass')
|
||||
|
||||
def make_deferred_light_pass(stages, node_group, node, shader_references, asset_references):
|
||||
# make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['gbuffer', 'shadowMap'], shader_context='deferred_light/deferred_light/deferred_light')
|
||||
# Draw lamp volume - TODO: properly generate stage
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['gbuffer', 'shadowMap'], shader_context='deferred_light/deferred_light/deferred_light')
|
||||
stages[-1]['command'] = 'draw_lamp_volume'
|
||||
|
||||
def make_volumetric_light_pass(stages, node_group, node, shader_references, asset_references):
|
||||
# Draw lamp volume - TODO: properly generate stage
|
||||
# make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[5, 6], bind_target_constants=['gbufferD', 'shadowMap'], shader_context='volumetric_light/volumetric_light/volumetric_light_blend')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=2, bind_target_indices=[5, 6], bind_target_constants=['gbufferD', 'shadowMap'], shader_context='volumetric_light/volumetric_light/volumetric_light')
|
||||
stages[-1]['command'] = 'draw_lamp_volume'
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=3, bind_target_indices=[2, 4], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_edge_pass/blur_edge_pass/blur_edge_pass_x')
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[3, 4], bind_target_constants=['tex', 'gbuffer0'], shader_context='blur_edge_pass/blur_edge_pass/blur_edge_pass_y_blend_add')
|
||||
|
||||
def make_deferred_indirect_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2, 3], bind_target_constants=['gbuffer', 'ssaotex'], shader_context='deferred_indirect/deferred_indirect/deferred_indirect')
|
||||
|
||||
def make_translucent_resolve_pass(stages, node_group, node, shader_references, asset_references):
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references, target_index=1, bind_target_indices=[2], bind_target_constants=['gbuffer'], shader_context='translucent_resolve/translucent_resolve/translucent_resolve')
|
||||
|
||||
# Returns merge node
|
||||
def buildNode(stages, node, node_group, shader_references, asset_references):
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
|
||||
append_stage = True
|
||||
|
||||
if node.bl_idname == 'MergeStagesNodeType':
|
||||
return node
|
||||
|
||||
elif node.bl_idname == 'SetTargetNodeType':
|
||||
buildNode.last_bind_target = None
|
||||
make_set_target(stage, node_group, node)
|
||||
|
||||
elif node.bl_idname == 'ClearTargetNodeType':
|
||||
color_val = None
|
||||
depth_val = None
|
||||
stencil_val = None
|
||||
if node.inputs[1].default_value == True:
|
||||
if node.inputs[2].is_linked: # Assume background color node is linked
|
||||
color_val = -1 # Clear to world.background_color
|
||||
else:
|
||||
color_val = node.inputs[2].default_value
|
||||
if node.inputs[3].default_value == True:
|
||||
depth_val = node.inputs[4].default_value
|
||||
if node.inputs[5].default_value == True:
|
||||
stencil_val = node.inputs[6].default_value
|
||||
make_clear_target(stage, color_val=color_val, depth_val=depth_val, stencil_val=stencil_val)
|
||||
|
||||
elif node.bl_idname == 'DrawMeshesNodeType':
|
||||
make_draw_meshes(stage, node_group, node)
|
||||
|
||||
elif node.bl_idname == 'DrawDecalsNodeType':
|
||||
make_draw_decals(stage, node_group, node, shader_references, asset_references)
|
||||
|
||||
elif node.bl_idname == 'BindTargetNodeType':
|
||||
if buildNode.last_bind_target is not None:
|
||||
stage = buildNode.last_bind_target
|
||||
append_stage = False
|
||||
buildNode.last_bind_target = stage
|
||||
constant_name = node.inputs[2].default_value
|
||||
make_bind_target(stage, node_group, node, constant_name)
|
||||
|
||||
elif node.bl_idname == 'DrawMaterialQuadNodeType':
|
||||
make_draw_material_quad(stage, node_group, node, shader_references, asset_references)
|
||||
|
||||
elif node.bl_idname == 'DrawQuadNodeType':
|
||||
make_draw_quad(stage, node_group, node, shader_references, asset_references)
|
||||
|
||||
elif node.bl_idname == 'DrawWorldNodeType':
|
||||
# Bind depth for quad
|
||||
# if node.inputs[1].is_linked:
|
||||
# stage = {}
|
||||
# stage['params'] = []
|
||||
# buildNode.last_bind_target = stage
|
||||
# if node.inputs[1].is_linked:
|
||||
# make_bind_target(stage, node_group, node, target_index=1, constant_name='gbufferD')
|
||||
# stages.append(stage)
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
# Draw quad
|
||||
# make_draw_world(stage, node_group, node, shader_references, asset_references, dome=False)
|
||||
# Draw dome
|
||||
make_draw_world(stage, node_group, node, shader_references, asset_references, dome=True)
|
||||
|
||||
elif node.bl_idname == 'DrawCompositorNodeType' or node.bl_idname == 'DrawCompositorWithFXAANodeType':
|
||||
# Set target
|
||||
if node.inputs[1].is_linked:
|
||||
make_set_target(stage, node_group, node)
|
||||
stages.append(stage)
|
||||
# Bind targets
|
||||
if node.inputs[2].is_linked or node.inputs[3].is_linked or node.inputs[4].is_linked:
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
buildNode.last_bind_target = stage
|
||||
if node.inputs[2].is_linked:
|
||||
make_bind_target(stage, node_group, node, target_index=2, constant_name='tex')
|
||||
if node.inputs[3].is_linked:
|
||||
make_bind_target(stage, node_group, node, target_index=3, constant_name='gbufferD')
|
||||
if node.inputs[4].is_linked:
|
||||
make_bind_target(stage, node_group, node, target_index=4, constant_name='gbuffer0')
|
||||
stages.append(stage)
|
||||
# Draw quad
|
||||
stage = {}
|
||||
stage['params'] = []
|
||||
with_fxaa = node.bl_idname == 'DrawCompositorWithFXAANodeType'
|
||||
make_draw_compositor(stage, node_group, node, shader_references, asset_references, with_fxaa=with_fxaa)
|
||||
|
||||
elif node.bl_idname == 'BranchFunctionNodeType':
|
||||
make_branch_function(stage, node_group, node)
|
||||
stages.append(stage)
|
||||
process_call_function(stage, stages, node, node_group, shader_references, asset_references)
|
||||
return
|
||||
|
||||
elif node.bl_idname == 'LoopStagesNodeType':
|
||||
# Just repeats the commands
|
||||
append_stage = False
|
||||
if node.outputs[1].is_linked:
|
||||
count = node.inputs[2].default_value
|
||||
for i in range(0, count):
|
||||
loopNode = findNodeByLinkFrom(node_group, node, node.outputs[1])
|
||||
buildNode(stages, loopNode, node_group, shader_references, asset_references)
|
||||
|
||||
elif node.bl_idname == 'LoopLampsNodeType':
|
||||
append_stage = False
|
||||
stage['command'] = 'loop_lamps'
|
||||
stages.append(stage)
|
||||
stage['returns_true'] = []
|
||||
if node.outputs[1].is_linked:
|
||||
loopNode = findNodeByLinkFrom(node_group, node, node.outputs[1])
|
||||
buildNode(stage['returns_true'], loopNode, node_group, shader_references, asset_references)
|
||||
|
||||
elif node.bl_idname == 'DrawStereoNodeType':
|
||||
append_stage = False
|
||||
stage['command'] = 'draw_stereo'
|
||||
stages.append(stage)
|
||||
stage['returns_true'] = []
|
||||
if node.outputs[1].is_linked:
|
||||
loopNode = findNodeByLinkFrom(node_group, node, node.outputs[1])
|
||||
buildNode(stage['returns_true'], loopNode, node_group, shader_references, asset_references)
|
||||
|
||||
elif node.bl_idname == 'CallFunctionNodeType':
|
||||
make_call_function(stage, node_group, node)
|
||||
|
||||
elif node.bl_idname == 'QuadPassNodeType':
|
||||
make_quad_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
|
||||
elif node.bl_idname == 'SSAOPassNodeType':
|
||||
make_ssao_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'SSAOReprojectPassNodeType':
|
||||
make_ssao_reproject_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'ApplySSAOPassNodeType':
|
||||
make_apply_ssao_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'SSRPassNodeType':
|
||||
make_ssr_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'BloomPassNodeType':
|
||||
make_bloom_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'MotionBlurPassNodeType':
|
||||
make_motion_blur_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'MotionBlurVelocityPassNodeType':
|
||||
make_motion_blur_velocity_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'CopyPassNodeType':
|
||||
make_copy_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'BlendPassNodeType':
|
||||
make_blend_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'CombinePassNodeType':
|
||||
make_combine_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'BlurBasicPassNodeType':
|
||||
make_blur_basic_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'DebugNormalsPassNodeType':
|
||||
make_debug_normals_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'FXAAPassNodeType':
|
||||
make_fxaa_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'SMAAPassNodeType':
|
||||
make_smaa_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'TAAPassNodeType':
|
||||
make_taa_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'SSSPassNodeType':
|
||||
make_sss_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'WaterPassNodeType':
|
||||
make_water_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'DeferredLightPassNodeType':
|
||||
make_deferred_light_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'DeferredIndirectPassNodeType':
|
||||
make_deferred_indirect_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'VolumetricLightPassNodeType':
|
||||
make_volumetric_light_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
elif node.bl_idname == 'TranslucentResolvePassNodeType':
|
||||
make_translucent_resolve_pass(stages, node_group, node, shader_references, asset_references)
|
||||
append_stage = False
|
||||
|
||||
if append_stage:
|
||||
stages.append(stage)
|
||||
|
||||
# Build next stage
|
||||
if node.outputs[0].is_linked:
|
||||
stageNode = findNodeByLinkFrom(node_group, node, node.outputs[0])
|
||||
buildNode(stages, stageNode, node_group, shader_references, asset_references)
|
||||
# Used to merge bind target nodes into one stage
|
||||
buildNode.last_bind_target = None
|
||||
# Used to determine shadowmap size
|
||||
buildNode.last_set_target_w = 0
|
||||
buildNode.last_set_target_h = 0
|
||||
|
||||
|
||||
def findNodeByLink(node_group, to_node, inp):
|
||||
for link in node_group.links:
|
||||
if link.to_node == to_node and link.to_socket == inp:
|
||||
return link.from_node
|
||||
|
||||
def findLink(node_group, to_node, inp):
|
||||
for link in node_group.links:
|
||||
if link.to_node == to_node and link.to_socket == inp:
|
||||
return link
|
||||
|
||||
def findNodeByLinkFrom(node_group, from_node, outp):
|
||||
for link in node_group.links:
|
||||
if link.from_node == from_node and link.from_socket == outp:
|
||||
return link.to_node
|
||||
|
||||
def get_root_node(node_group):
|
||||
# Find first node linked to begin node
|
||||
rn = None
|
||||
for n in node_group.nodes:
|
||||
if n.bl_idname == 'BeginNodeType':
|
||||
# Store contexts
|
||||
buildNodeTree.cam.renderpath_id = n.inputs[0].default_value
|
||||
mesh_contexts = n.inputs[1].default_value.split(',')
|
||||
buildNodeTree.cam.mesh_context = mesh_contexts[0]
|
||||
if len(mesh_contexts) > 1:
|
||||
buildNodeTree.cam.mesh_context_empty = mesh_contexts[1]
|
||||
buildNodeTree.cam.shadows_context = n.inputs[2].default_value
|
||||
buildNodeTree.cam.translucent_context = n.inputs[3].default_value
|
||||
buildNodeTree.cam.overlay_context = n.inputs[4].default_value
|
||||
if n.inputs[5].default_value == False: # No HDR space lighting, append def
|
||||
bpy.data.worlds['Arm'].world_defs += '_LDR'
|
||||
rn = findNodeByLinkFrom(node_group, n, n.outputs[0])
|
||||
break
|
||||
return rn
|
||||
|
||||
def preprocess_renderpath(root_node, node_group):
|
||||
render_targets = []
|
||||
depth_buffers = []
|
||||
preprocess_renderpath.velocity_def_added = False
|
||||
buildNodeTree.cam.renderpath_passes = ''
|
||||
traverse_renderpath(root_node, node_group, render_targets, depth_buffers)
|
||||
return render_targets, depth_buffers
|
||||
|
||||
def traverse_renderpath(node, node_group, render_targets, depth_buffers):
|
||||
# Gather linked draw geometry contexts
|
||||
if node.bl_idname == 'DrawMeshesNodeType':
|
||||
if buildNodeTree.cam.renderpath_passes != '':
|
||||
buildNodeTree.cam.renderpath_passes += '_' # Separator
|
||||
buildNodeTree.cam.renderpath_passes += node.inputs[1].default_value
|
||||
|
||||
# Gather defs from linked nodes
|
||||
if node.bl_idname == 'TAAPassNodeType' or node.bl_idname == 'MotionBlurVelocityPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType':
|
||||
if preprocess_renderpath.velocity_def_added == False:
|
||||
assets.add_khafile_def('WITH_VELOC')
|
||||
bpy.data.worlds['Arm'].world_defs += '_Veloc'
|
||||
preprocess_renderpath.velocity_def_added = True
|
||||
if node.bl_idname == 'TAAPassNodeType':
|
||||
assets.add_khafile_def('WITH_TAA')
|
||||
# bpy.data.worlds['Arm'].world_defs += '_TAA'
|
||||
elif node.bl_idname == 'SMAAPassNodeType':
|
||||
bpy.data.worlds['Arm'].world_defs += '_SMAA'
|
||||
|
||||
elif node.bl_idname == 'SSAOPassNodeType' or node.bl_idname == 'ApplySSAOPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType':
|
||||
if bpy.data.worlds['Arm'].generate_ssao: # SSAO enabled
|
||||
bpy.data.worlds['Arm'].world_defs += '_SSAO'
|
||||
|
||||
elif node.bl_idname == 'DrawStereoNodeType':
|
||||
assets.add_khafile_def('WITH_VR')
|
||||
bpy.data.worlds['Arm'].world_defs += '_VR'
|
||||
|
||||
# Collect render targets
|
||||
if node.bl_idname == 'SetTargetNodeType' or node.bl_idname == 'QuadPassNodeType' or node.bl_idname == 'DrawCompositorNodeType' or node.bl_idname == 'DrawCompositorWithFXAANodeType':
|
||||
if node.inputs[1].is_linked:
|
||||
tnode = findNodeByLink(node_group, node, node.inputs[1])
|
||||
parse_render_target(tnode, node_group, render_targets, depth_buffers)
|
||||
|
||||
# Traverse loops
|
||||
elif node.bl_idname == 'LoopStagesNodeType' or node.bl_idname == 'LoopLampsNodeType' or node.bl_idname == 'DrawStereoNodeType':
|
||||
if node.outputs[1].is_linked:
|
||||
loop_node = findNodeByLinkFrom(node_group, node, node.outputs[1])
|
||||
traverse_renderpath(loop_node, node_group, render_targets, depth_buffers)
|
||||
|
||||
# Prebuilt
|
||||
elif node.bl_idname == 'MotionBlurPassNodeType' or node.bl_idname == 'MotionBlurVelocityPassNodeType' or node.bl_idname == 'CopyPassNodeType' or node.bl_idname == 'BlendPassNodeType' or node.bl_idname == 'CombinePassNodeType' or node.bl_idname == 'DebugNormalsPassNodeType' or node.bl_idname == 'FXAAPassNodeType' or node.bl_idname == 'TAAPassNodeType' or node.bl_idname == 'WaterPassNodeType' or node.bl_idname == 'DeferredLightPassNodeType' or node.bl_idname == 'DeferredIndirectPassNodeType' or node.bl_idname == 'VolumetricLightPassNodeType' or node.bl_idname == 'TranslucentResolvePassNodeType':
|
||||
if node.inputs[1].is_linked:
|
||||
tnode = findNodeByLink(node_group, node, node.inputs[1])
|
||||
parse_render_target(tnode, node_group, render_targets, depth_buffers)
|
||||
elif node.bl_idname == 'SSRPassNodeType' or node.bl_idname == 'ApplySSAOPassNodeType' or node.bl_idname == 'BloomPassNodeType' or node.bl_idname == 'SMAAPassNodeType':
|
||||
for i in range(1, 4):
|
||||
if node.inputs[i].is_linked:
|
||||
tnode = findNodeByLink(node_group, node, node.inputs[i])
|
||||
parse_render_target(tnode, node_group, render_targets, depth_buffers)
|
||||
elif node.bl_idname == 'SSAOPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType' or node.bl_idname == 'SSSPassNodeType' or node.bl_idname == 'BlurBasicPassNodeType':
|
||||
for i in range(1, 3):
|
||||
if node.inputs[i].is_linked:
|
||||
tnode = findNodeByLink(node_group, node, node.inputs[i])
|
||||
parse_render_target(tnode, node_group, render_targets, depth_buffers)
|
||||
|
||||
# Next stage
|
||||
if node.outputs[0].is_linked:
|
||||
stagenode = findNodeByLinkFrom(node_group, node, node.outputs[0])
|
||||
traverse_renderpath(stagenode, node_group, render_targets, depth_buffers)
|
||||
|
||||
def parse_render_target(node, node_group, render_targets, depth_buffers):
|
||||
if node.bl_idname == 'NodeReroute':
|
||||
tnode = findNodeByLink(node_group, node, node.inputs[0])
|
||||
parse_render_target(tnode, node_group, render_targets, depth_buffers)
|
||||
|
||||
elif node.bl_idname == 'TargetNodeType':
|
||||
# Target already exists
|
||||
id = node.inputs[0].default_value
|
||||
for t in render_targets:
|
||||
if t['name'] == id:
|
||||
return
|
||||
|
||||
depth_buffer_id = None
|
||||
if node.inputs[3].is_linked:
|
||||
# Find depth buffer
|
||||
depth_node = findNodeByLink(node_group, node, node.inputs[3])
|
||||
depth_buffer_id = depth_node.inputs[0].default_value
|
||||
# Append depth buffer
|
||||
found = False
|
||||
for db in depth_buffers:
|
||||
if db['name'] == depth_buffer_id:
|
||||
found = True
|
||||
break
|
||||
if found == False:
|
||||
db = {}
|
||||
db['name'] = depth_buffer_id
|
||||
db['stencil_buffer'] = depth_node.inputs[1].default_value
|
||||
depth_buffers.append(db)
|
||||
# Get scale
|
||||
scale = 1.0
|
||||
if node.inputs[1].is_linked:
|
||||
size_node = findNodeByLink(node_group, node, node.inputs[1])
|
||||
while size_node.bl_idname == 'NodeReroute': # Step through reroutes
|
||||
size_node = findNodeByLink(node_group, size_node, size_node.inputs[0])
|
||||
scale = size_node.inputs[0].default_value
|
||||
|
||||
# Append target
|
||||
target = make_render_target(node, scale, depth_buffer_id=depth_buffer_id)
|
||||
render_targets.append(target)
|
||||
|
||||
elif node.bl_idname == 'GBufferNodeType':
|
||||
for i in range(0, 5):
|
||||
if node.inputs[i].is_linked:
|
||||
n = findNodeByLink(node_group, node, node.inputs[i])
|
||||
parse_render_target(n, node_group, render_targets, depth_buffers)
|
||||
|
||||
def make_render_target(n, scale, depth_buffer_id=None):
|
||||
target = {}
|
||||
target['name'] = n.inputs[0].default_value
|
||||
target['width'] = n.inputs[1].default_value
|
||||
target['height'] = n.inputs[2].default_value
|
||||
target['format'] = n.inputs[4].default_value
|
||||
if n.inputs[5].default_value:
|
||||
target['ping_pong'] = True
|
||||
if scale != 1.0:
|
||||
target['scale'] = scale
|
||||
if depth_buffer_id != None:
|
||||
target['depth_buffer'] = depth_buffer_id
|
||||
return target
|
|
@ -7,14 +7,6 @@ import write_probes
|
|||
import assets
|
||||
import utils
|
||||
|
||||
def register():
|
||||
pass
|
||||
#bpy.utils.register_module(__name__)
|
||||
|
||||
def unregister():
|
||||
pass
|
||||
#bpy.utils.unregister_module(__name__)
|
||||
|
||||
def find_node(node_group, to_node, target_socket):
|
||||
for link in node_group.links:
|
||||
if link.to_node == to_node and link.to_socket == target_socket:
|
||||
|
@ -203,7 +195,7 @@ def parse_color(world, node, context, envmap_strength_const):
|
|||
|
||||
# Irradiance json file name
|
||||
base_name = utils.safe_filename(world.name)
|
||||
world.world_envtex_name = base_name
|
||||
world.world_envtex_name = base_name + '.hdr' # Fake extension
|
||||
|
||||
write_probes.write_sky_irradiance(base_name)
|
||||
|
|
@ -48,6 +48,7 @@ class TimeNode(Node, ArmLogicTreeNode):
|
|||
self.outputs.new('NodeSocketFloat', "Time")
|
||||
|
||||
class VectorNode(Node, ArmLogicTreeNode):
|
||||
'''Vector node'''
|
||||
bl_idname = 'VectorNodeType'
|
||||
# Label for nice name display
|
||||
bl_label = 'Vector'
|
||||
|
@ -62,6 +63,7 @@ class VectorNode(Node, ArmLogicTreeNode):
|
|||
self.outputs.new('NodeSocketVector', "Vector")
|
||||
|
||||
class ScaleValueNode(Node, ArmLogicTreeNode):
|
||||
'''Scale value node'''
|
||||
bl_idname = 'ScaleValueNodeType'
|
||||
bl_label = 'ScaleValue'
|
||||
bl_icon = 'CURVE_PATH'
|
||||
|
@ -74,6 +76,7 @@ class ScaleValueNode(Node, ArmLogicTreeNode):
|
|||
self.outputs.new('NodeSocketFloat', "Value")
|
||||
|
||||
class SineNode(Node, ArmLogicTreeNode):
|
||||
'''Sine node'''
|
||||
bl_idname = 'SineNodeType'
|
||||
bl_label = 'Sine'
|
||||
bl_icon = 'CURVE_PATH'
|
||||
|
@ -84,6 +87,7 @@ class SineNode(Node, ArmLogicTreeNode):
|
|||
self.outputs.new('NodeSocketFloat', "Value")
|
||||
|
||||
class ThisNode(Node, ArmLogicTreeNode):
|
||||
'''This node'''
|
||||
bl_idname = 'ThisNodeType'
|
||||
bl_label = 'This'
|
||||
bl_icon = 'GAME'
|
||||
|
@ -92,6 +96,7 @@ class ThisNode(Node, ArmLogicTreeNode):
|
|||
self.outputs.new('NodeSocketShader', "Target")
|
||||
|
||||
class PickerNode(Node, ArmLogicTreeNode):
|
||||
'''Picker node'''
|
||||
bl_idname = 'PickerNodeType'
|
||||
bl_label = 'Picker'
|
||||
bl_icon = 'GAME'
|
||||
|
@ -104,6 +109,7 @@ class PickerNode(Node, ArmLogicTreeNode):
|
|||
layout.prop_search(self, "property0", context.scene, "objects", text = "")
|
||||
|
||||
class SetTransformNode(Node, ArmLogicTreeNode):
|
||||
'''Set transform node'''
|
||||
bl_idname = 'SetTransformNodeType'
|
||||
bl_label = 'Set Transform'
|
||||
bl_icon = 'GAME'
|
||||
|
@ -113,6 +119,7 @@ class SetTransformNode(Node, ArmLogicTreeNode):
|
|||
self.inputs.new('NodeSocketShader', "Transform")
|
||||
|
||||
class SetVisibleNode(Node, ArmLogicTreeNode):
|
||||
'''Set visible node'''
|
||||
bl_idname = 'SetVisibleNodeType'
|
||||
bl_label = 'Set Visible'
|
||||
bl_icon = 'GAME'
|
||||
|
@ -122,6 +129,7 @@ class SetVisibleNode(Node, ArmLogicTreeNode):
|
|||
self.inputs.new('NodeSocketShader', "Bool")
|
||||
|
||||
class GreaterThanNode(Node, ArmLogicTreeNode):
|
||||
'''Greater than node'''
|
||||
bl_idname = 'GreaterThanNodeType'
|
||||
bl_label = 'Greater Than'
|
||||
bl_icon = 'GAME'
|
||||
|
@ -186,108 +194,3 @@ def register():
|
|||
def unregister():
|
||||
nodeitems_utils.unregister_node_categories("ARM_LOGIC_NODES")
|
||||
bpy.utils.unregister_module(__name__)
|
||||
|
||||
# Generating node sources
|
||||
def buildNodeTrees():
|
||||
s = bpy.data.filepath.split(os.path.sep)
|
||||
s.pop()
|
||||
fp = os.path.sep.join(s)
|
||||
os.chdir(fp)
|
||||
|
||||
# Make sure package dir exists
|
||||
nodes_path = 'Sources/' + bpy.data.worlds['Arm'].ArmProjectPackage.replace(".", "/") + "/node"
|
||||
if not os.path.exists(nodes_path):
|
||||
os.makedirs(nodes_path)
|
||||
|
||||
# Export node scripts
|
||||
for node_group in bpy.data.node_groups:
|
||||
if node_group.bl_idname == 'ArmLogicTreeType': # Build only game trees
|
||||
node_group.use_fake_user = True # Keep fake references for now
|
||||
buildNodeTree(node_group)
|
||||
|
||||
def buildNodeTree(node_group):
|
||||
path = 'Sources/' + bpy.data.worlds['Arm'].ArmProjectPackage.replace('.', '/') + '/node/'
|
||||
node_group_name = node_group.name.replace('.', '_').replace(' ', '')
|
||||
|
||||
with open(path + node_group_name + '.hx', 'w') as f:
|
||||
f.write('package ' + bpy.data.worlds['Arm'].ArmProjectPackage + '.node;\n\n')
|
||||
f.write('import armory.logicnode.*;\n\n')
|
||||
f.write('class ' + node_group_name + ' extends armory.trait.internal.NodeExecutor {\n\n')
|
||||
f.write('\tpublic function new() { super(); notifyOnAdd(add); }\n\n')
|
||||
f.write('\tfunction add() {\n')
|
||||
# Make sure root node exists
|
||||
roots = get_root_nodes(node_group)
|
||||
created_nodes = []
|
||||
for rn in roots:
|
||||
name = '_' + rn.name.replace('.', '_').replace(' ', '')
|
||||
buildNode(node_group, rn, f, created_nodes)
|
||||
f.write('\n\t\tstart(' + name + ');\n\n')
|
||||
f.write('\t}\n')
|
||||
f.write('}\n')
|
||||
|
||||
def buildNode(node_group, node, f, created_nodes):
|
||||
# Get node name
|
||||
name = '_' + node.name.replace('.', '_').replace(' ', '')
|
||||
|
||||
# Check if node already exists
|
||||
for n in created_nodes:
|
||||
if n == name:
|
||||
return name
|
||||
|
||||
# Create node
|
||||
type = node.name.split(".")[0].replace(' ', '') + "Node"
|
||||
f.write('\t\tvar ' + name + ' = new ' + type + '();\n')
|
||||
created_nodes.append(name)
|
||||
|
||||
# Properties
|
||||
if hasattr(node, "property0"):
|
||||
f.write('\t\t' + name + '.property0 = "' + node.property0 + '";\n')
|
||||
if hasattr(node, "property1"):
|
||||
f.write('\t\t' + name + '.property1 = "' + node.property1 + '";\n')
|
||||
if hasattr(node, "property2"):
|
||||
f.write('\t\t' + name + '.property2 = "' + node.property2 + '";\n')
|
||||
if hasattr(node, "property3"):
|
||||
f.write('\t\t' + name + '.property3 = "' + node.property3 + '";\n')
|
||||
if hasattr(node, "property4"):
|
||||
f.write('\t\t' + name + '.property4 = "' + node.property4 + '";\n')
|
||||
|
||||
# Create inputs
|
||||
for inp in node.inputs:
|
||||
# Is linked - find node
|
||||
inpname = ''
|
||||
if inp.is_linked:
|
||||
n = findNodeByLink(node_group, node, inp)
|
||||
inpname = buildNode(node_group, n, f, created_nodes)
|
||||
# Not linked - create node with default values
|
||||
else:
|
||||
inpname = build_default_node(inp)
|
||||
|
||||
# Add input
|
||||
f.write('\t\t' + name + '.inputs.push(' + inpname + ');\n')
|
||||
|
||||
return name
|
||||
|
||||
def findNodeByLink(node_group, to_node, inp):
|
||||
for link in node_group.links:
|
||||
if link.to_node == to_node and link.to_socket == inp:
|
||||
if link.from_node.bl_idname == 'NodeReroute': # Step through reroutes
|
||||
return findNodeByLink(node_group, link.from_node, link.from_node.inputs[0])
|
||||
return link.from_node
|
||||
|
||||
def get_root_nodes(node_group):
|
||||
roots = []
|
||||
for n in node_group.nodes:
|
||||
if len(n.outputs) == 0: # Assume node with no outputs as roots
|
||||
roots.append(n)
|
||||
return roots
|
||||
|
||||
def build_default_node(inp):
|
||||
inpname = ''
|
||||
if inp.type == "VECTOR":
|
||||
inpname = 'VectorNode.create(' + str(inp.default_value[0]) + ', ' + str(inp.default_value[1]) + ", " + str(inp.default_value[2]) + ')'
|
||||
elif inp.type == "VALUE":
|
||||
inpname = 'FloatNode.create(' + str(inp.default_value) + ')'
|
||||
elif inp.type == 'BOOLEAN':
|
||||
inpname = 'BoolNode.create(' + str(inp.default_value).lower() + ')'
|
||||
|
||||
return inpname
|
||||
|
|
File diff suppressed because it is too large
Load diff
403
blender/props.py
403
blender/props.py
|
@ -3,11 +3,11 @@ import bpy
|
|||
import os
|
||||
import json
|
||||
import subprocess
|
||||
import nodes_renderpath
|
||||
import make_renderpath
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from bpy.props import *
|
||||
from traits_clip import *
|
||||
from traits_action import *
|
||||
from props_traits_clip import *
|
||||
from props_traits_action import *
|
||||
import utils
|
||||
import make
|
||||
import space_armory
|
||||
|
@ -18,6 +18,25 @@ try:
|
|||
except ImportError:
|
||||
pass
|
||||
|
||||
def parse_operator(text):
|
||||
if text == None:
|
||||
return
|
||||
# Proof of concept..
|
||||
text = text.split(' ', 1)
|
||||
if len(text) > 1:
|
||||
text = text[1]
|
||||
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')
|
||||
elif cmd[1] == 'setx':
|
||||
bpy.context.scene.objects[cmd[2]].location.x = float(cmd[3])
|
||||
elif cmd[1] == 'select':
|
||||
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 on_scene_update_post(context):
|
||||
global last_time
|
||||
|
||||
|
@ -25,16 +44,21 @@ def on_scene_update_post(context):
|
|||
last_time = time.time()
|
||||
|
||||
# Tag redraw if playing in space_armory
|
||||
make.play_project.last_chromium_running = make.play_project.chromium_running
|
||||
make.play_project.chromium_running = False
|
||||
if space_armory.SPACEARMORY_HT_header.is_paused == False:
|
||||
for area in bpy.context.screen.areas:
|
||||
if area.type == 'VIEW_GAME':
|
||||
area.tag_redraw()
|
||||
make.play_project.chromium_running = True
|
||||
for area in bpy.context.screen.areas:
|
||||
if area.type == 'VIEW_GAME':
|
||||
make.play_project.chromium_running = True
|
||||
bgame.draw()
|
||||
|
||||
# Have to update chromium one more time before exit, to prevent 'AudioSyncReader::Read timed out' warnings
|
||||
if make.play_project.chromium_running == False:
|
||||
if make.play_project.last_chromium_running:
|
||||
bgame.draw()
|
||||
|
||||
# Auto patch on every operator change
|
||||
ops = bpy.context.window_manager.operators
|
||||
if (make.play_project.playproc != None or make.play_project.chromium_running) and \
|
||||
if make.play_project.chromium_running and \
|
||||
bpy.data.worlds['Arm'].ArmPlayLivePatch and \
|
||||
bpy.data.worlds['Arm'].ArmPlayAutoBuild and \
|
||||
len(ops) > 0 and \
|
||||
|
@ -72,6 +96,9 @@ def on_scene_update_post(context):
|
|||
# Read chromium console
|
||||
if bgame.get_console_updated() == 1:
|
||||
make.armory_space_log(bgame.get_console())
|
||||
# Read operator console
|
||||
if bgame.get_operator_updated() == 1:
|
||||
parse_operator(bgame.get_operator())
|
||||
break
|
||||
|
||||
# New output has been logged
|
||||
|
@ -83,7 +110,7 @@ def on_scene_update_post(context):
|
|||
break
|
||||
|
||||
# Player finished, redraw play buttons
|
||||
if make.play_project.playproc_finished:
|
||||
if make.play_project.playproc_finished or make.play_project.compileproc_finished:
|
||||
make.play_project.playproc_finished = False
|
||||
for area in bpy.context.screen.areas:
|
||||
if area.type == 'VIEW_3D' or area.type == 'PROPERTIES':
|
||||
|
@ -92,6 +119,9 @@ def on_scene_update_post(context):
|
|||
# Compilation finished
|
||||
if make.play_project.compileproc_finished:
|
||||
make.play_project.compileproc_finished = False
|
||||
for area in bpy.context.screen.areas:
|
||||
if area.type == 'VIEW_3D' or area.type == 'PROPERTIES':
|
||||
area.tag_redraw()
|
||||
# Notify embedded player
|
||||
if make.play_project.chromium_running:
|
||||
bgame.call_js('armory.Scene.patch();')
|
||||
|
@ -131,24 +161,29 @@ def invalidate_mesh_data(self, context):
|
|||
if os.path.isdir(fp + '/build/compiled/Assets/meshes'):
|
||||
shutil.rmtree(fp + '/build/compiled/Assets/meshes')
|
||||
|
||||
def get_arm_progress(self):
|
||||
return ArmoryProjectPanel.progress
|
||||
|
||||
def initProperties():
|
||||
# For project
|
||||
bpy.types.World.ArmVersion = StringProperty(name = "ArmVersion", default="")
|
||||
bpy.types.World.ArmProgress = bpy.props.FloatProperty(name="Progress", description="Current build progress", default=100.0, min=0.0, max=100.0, soft_min=0.0, soft_max=100.0, subtype='PERCENTAGE', get=get_arm_progress)
|
||||
bpy.types.World.ArmVersion = StringProperty(name="ArmVersion", description="Armory SDK version", default="")
|
||||
target_prop = EnumProperty(
|
||||
items = [('html5', 'HTML5', 'html5'),
|
||||
('windows', 'Windows', 'windows'),
|
||||
items = [('html5', 'HTML5', 'html5'),
|
||||
('windows', 'Windows', 'windows'),
|
||||
('macos', 'MacOS', 'macos'),
|
||||
('linux', 'Linux', 'linux'),
|
||||
('linux', 'Linux', 'linux'),
|
||||
('ios', 'iOS', 'ios'),
|
||||
('android-native', 'Android', 'android-native')],
|
||||
name = "Target", default='html5')
|
||||
name="Target", default='html5',
|
||||
description='Build paltform')
|
||||
bpy.types.World.ArmProjectTarget = target_prop
|
||||
bpy.types.World.ArmPublishTarget = target_prop
|
||||
bpy.types.World.ArmProjectName = StringProperty(name = "Name", default="ArmoryGame")
|
||||
bpy.types.World.ArmProjectPackage = StringProperty(name = "Package", default="game")
|
||||
bpy.types.World.ArmPlayActiveScene = BoolProperty(name="Play Active Scene", default=True)
|
||||
bpy.types.World.ArmProjectScene = StringProperty(name = "Scene")
|
||||
bpy.types.World.ArmProjectSamplesPerPixel = IntProperty(name = "Samples per Pixel", default=1)
|
||||
bpy.types.World.ArmProjectName = StringProperty(name="Name", description="Exported project name", default="ArmoryProject")
|
||||
bpy.types.World.ArmProjectPackage = StringProperty(name="Package", description="Package name for scripts", default="arm")
|
||||
bpy.types.World.ArmPlayActiveScene = BoolProperty(name="Play Active Scene", description="Load currently edited scene when launching player", default=True)
|
||||
bpy.types.World.ArmProjectScene = StringProperty(name="Scene", description="Scene to load when launching player")
|
||||
bpy.types.World.ArmProjectSamplesPerPixel = IntProperty(name="Samples per Pixel", description="MSAA samples usable for render paths drawing directly to framebuffer", default=1)
|
||||
bpy.types.World.ArmPhysics = EnumProperty(
|
||||
items = [('Disabled', 'Disabled', 'Disabled'),
|
||||
('Bullet', 'Bullet', 'Bullet')],
|
||||
|
@ -157,32 +192,35 @@ def initProperties():
|
|||
items = [('Disabled', 'Disabled', 'Disabled'),
|
||||
('Recast', 'Recast', 'Recast')],
|
||||
name = "Navigation", default='Disabled')
|
||||
bpy.types.World.ArmKhafile = StringProperty(name = "Khafile")
|
||||
bpy.types.World.ArmMinimize = BoolProperty(name="Minimize Data", default=True, update=invalidate_compiled_data)
|
||||
bpy.types.World.ArmOptimizeMesh = BoolProperty(name="Optimize Meshes", default=False, update=invalidate_mesh_data)
|
||||
bpy.types.World.ArmSampledAnimation = BoolProperty(name="Sampled Animation", default=False, update=invalidate_compiled_data)
|
||||
bpy.types.World.ArmDeinterleavedBuffers = BoolProperty(name="Deinterleaved Buffers", default=False)
|
||||
bpy.types.World.ArmExportHideRender = BoolProperty(name="Export Hidden Renders", default=False)
|
||||
bpy.types.World.ArmSpawnAllLayers = BoolProperty(name="Spawn All Layers", default=False)
|
||||
bpy.types.World.ArmCacheShaders = BoolProperty(name="Cache Shaders", default=True, update=invalidate_shader_cache)
|
||||
bpy.types.World.ArmPlayLivePatch = BoolProperty(name="Live Patching", default=True)
|
||||
bpy.types.World.ArmPlayAutoBuild = BoolProperty(name="Auto Build", default=True)
|
||||
bpy.types.World.ArmPlayViewportCamera = BoolProperty(name="Viewport Camera", default=False)
|
||||
bpy.types.World.ArmKhafile = StringProperty(name = "Khafile", description="Source appended to khafile.js")
|
||||
bpy.types.World.ArmMinimize = BoolProperty(name="Minimize Data", description="Export scene data in binary", default=True, update=invalidate_compiled_data)
|
||||
bpy.types.World.ArmOptimizeMesh = BoolProperty(name="Optimize Meshes", description="Export more efficient geometry indices, can prolong build times", default=False, update=invalidate_mesh_data)
|
||||
bpy.types.World.ArmSampledAnimation = BoolProperty(name="Sampled Animation", description="Export object animation as raw matrices", default=False, update=invalidate_compiled_data)
|
||||
bpy.types.World.ArmDeinterleavedBuffers = BoolProperty(name="Deinterleaved Buffers", description="Use deinterleaved vertex buffers", default=False)
|
||||
bpy.types.World.ArmExportHideRender = BoolProperty(name="Export Hidden Renders", description="Export hidden objects", default=False)
|
||||
bpy.types.World.ArmSpawnAllLayers = BoolProperty(name="Spawn All Layers", description="Spawn objects from all scene layers", default=False)
|
||||
bpy.types.World.ArmPlayAdvanced = BoolProperty(name="Advanced", default=False)
|
||||
bpy.types.World.ArmBuildAdvanced = BoolProperty(name="Advanced", default=False)
|
||||
bpy.types.World.ArmProjectAdvanced = BoolProperty(name="Advanced", default=False)
|
||||
bpy.types.World.ArmObjectAdvanced = BoolProperty(name="Advanced", default=False)
|
||||
bpy.types.World.ArmCacheShaders = BoolProperty(name="Cache Shaders", description="Do not rebuild existing shaders", default=True, update=invalidate_shader_cache)
|
||||
bpy.types.World.ArmCleanEnvmaps = BoolProperty(name="Clean Envmaps", description="Remove prefiltered maps when cleaning project", default=True)
|
||||
bpy.types.World.ArmPlayLivePatch = BoolProperty(name="Live Patching", description="Sync running player data to Blender", default=True)
|
||||
bpy.types.World.ArmPlayAutoBuild = BoolProperty(name="Auto Build", description="Rebuild scene on operator changes", default=True)
|
||||
bpy.types.World.ArmPlayViewportCamera = BoolProperty(name="Viewport Camera", description="Start player at viewport camera position", default=False)
|
||||
bpy.types.World.ArmPlayViewportNavigation = EnumProperty(
|
||||
items = [('None', 'None', 'None'),
|
||||
('Walk', 'Walk', 'Walk')],
|
||||
name = "Navigation", default='Walk')
|
||||
bpy.types.World.ArmPlayConsole = BoolProperty(name="Debug Console", default=False)
|
||||
bpy.types.World.ArmPlayDeveloperTools = BoolProperty(name="Developer Tools", default=False)
|
||||
items=[('None', 'None', 'None'),
|
||||
('Walk', 'Walk', 'Walk')],
|
||||
name="Navigation", description="Enable camera controls", default='Walk')
|
||||
bpy.types.World.ArmPlayConsole = BoolProperty(name="Debug Console", description="Show inspector in player", default=False)
|
||||
bpy.types.World.ArmPlayDeveloperTools = BoolProperty(name="Developer Tools", description="Show chromium developer tools in player", default=False)
|
||||
bpy.types.World.ArmPlayRuntime = EnumProperty(
|
||||
items = [('Electron', 'Electron', 'Electron'),
|
||||
('Browser', 'Browser', 'Browser')],
|
||||
# ('Native', 'Native', 'Native')],
|
||||
#('Krom', 'Krom', 'Krom')],
|
||||
name = "Runtime", default='Electron')
|
||||
items=[('Electron', 'Electron', 'Electron'),
|
||||
('Browser', 'Browser', 'Browser')],
|
||||
name="Runtime", description="Player runtime used when launching in new window", default='Electron')
|
||||
|
||||
# For object
|
||||
bpy.types.Object.instanced_children = bpy.props.BoolProperty(name="Instanced Children", default=False)
|
||||
bpy.types.Object.instanced_children = bpy.props.BoolProperty(name="Instanced Children", description="Use instaced rendering", default=False)
|
||||
bpy.types.Object.instanced_children_loc_x = bpy.props.BoolProperty(name="X", default=True)
|
||||
bpy.types.Object.instanced_children_loc_y = bpy.props.BoolProperty(name="Y", default=True)
|
||||
bpy.types.Object.instanced_children_loc_z = bpy.props.BoolProperty(name="Z", default=True)
|
||||
|
@ -194,52 +232,55 @@ def initProperties():
|
|||
bpy.types.Object.instanced_children_scale_z = bpy.props.BoolProperty(name="Z", default=False)
|
||||
bpy.types.Object.override_material = bpy.props.BoolProperty(name="Override Material", default=False)
|
||||
bpy.types.Object.override_material_name = bpy.props.StringProperty(name="Name", default="")
|
||||
bpy.types.Object.game_export = bpy.props.BoolProperty(name="Export", default=True)
|
||||
bpy.types.Object.game_visible = bpy.props.BoolProperty(name="Visible", default=True)
|
||||
bpy.types.Object.game_export = bpy.props.BoolProperty(name="Export", description="Export object data", default=True)
|
||||
bpy.types.Object.game_visible = bpy.props.BoolProperty(name="Visible", description="Render this object", default=True)
|
||||
bpy.types.Object.spawn = bpy.props.BoolProperty(name="Spawn", description="Auto-add this object when creating scene", default=True)
|
||||
bpy.types.Object.mobile = bpy.props.BoolProperty(name="Mobile", description="Object moves during gameplay", default=True)
|
||||
# - Clips
|
||||
bpy.types.Object.bone_animation_enabled = bpy.props.BoolProperty(name="Bone Animation", default=True)
|
||||
bpy.types.Object.object_animation_enabled = bpy.props.BoolProperty(name="Object Animation", default=True)
|
||||
bpy.types.Object.edit_tracks_prop = bpy.props.BoolProperty(name="Edit Clips", description="A name for this item", default=False)
|
||||
bpy.types.Object.start_track_name_prop = bpy.props.StringProperty(name="Start Track", description="A name for this item", default="")
|
||||
bpy.types.Object.bone_animation_enabled = bpy.props.BoolProperty(name="Bone Animation", description="Enable skinning", default=True)
|
||||
bpy.types.Object.object_animation_enabled = bpy.props.BoolProperty(name="Object Animation", description="Enable timeline animation", default=True)
|
||||
bpy.types.Object.edit_tracks_prop = bpy.props.BoolProperty(name="Edit Clips", description="Manually set animation frames", default=False)
|
||||
bpy.types.Object.start_track_name_prop = bpy.props.StringProperty(name="Start Track", description="Play this track by default", default="")
|
||||
bpy.types.Object.my_cliptraitlist = bpy.props.CollectionProperty(type=ListClipTraitItem)
|
||||
bpy.types.Object.cliptraitlist_index = bpy.props.IntProperty(name="Index for my_list", default=0)
|
||||
bpy.types.Object.cliptraitlist_index = bpy.props.IntProperty(name="Clip index", default=0)
|
||||
# - Actions
|
||||
bpy.types.Object.edit_actions_prop = bpy.props.BoolProperty(name="Edit Actions", description="A name for this item", default=False)
|
||||
bpy.types.Object.start_action_name_prop = bpy.props.StringProperty(name="Start Action", description="A name for this item", default="")
|
||||
bpy.types.Object.edit_actions_prop = bpy.props.BoolProperty(name="Edit Actions", description="Manually set used actions", default=False)
|
||||
bpy.types.Object.start_action_name_prop = bpy.props.StringProperty(name="Start Action", description="Play this action by default", default="")
|
||||
# For speakers
|
||||
bpy.types.Speaker.loop = bpy.props.BoolProperty(name="Loop", description="Loop this sound", default=False)
|
||||
bpy.types.Speaker.stream = bpy.props.BoolProperty(name="Stream", description="Stream this sound", default=False)
|
||||
# For mesh
|
||||
bpy.types.Mesh.mesh_cached = bpy.props.BoolProperty(name="Mesh Cached", default=False)
|
||||
bpy.types.Mesh.mesh_cached_verts = bpy.props.IntProperty(name="Last Verts", default=0)
|
||||
bpy.types.Mesh.mesh_cached_edges = bpy.props.IntProperty(name="Last Edges", default=0)
|
||||
bpy.types.Mesh.static_usage = bpy.props.BoolProperty(name="Static Data Usage", default=True)
|
||||
bpy.types.Curve.mesh_cached = bpy.props.BoolProperty(name="Mesh Cached", default=False)
|
||||
bpy.types.Curve.static_usage = bpy.props.BoolProperty(name="Static Data Usage", default=True)
|
||||
bpy.types.Mesh.mesh_cached = bpy.props.BoolProperty(name="Mesh Cached", description="No need to reexport mesh data", default=False)
|
||||
bpy.types.Mesh.mesh_cached_verts = bpy.props.IntProperty(name="Last Verts", description="Number of vertices in last export", default=0)
|
||||
bpy.types.Mesh.mesh_cached_edges = bpy.props.IntProperty(name="Last Edges", description="Number of edges in last export", default=0)
|
||||
bpy.types.Mesh.dynamic_usage = bpy.props.BoolProperty(name="Dynamic Data Usage", description="Mesh data can change at runtime", default=False)
|
||||
bpy.types.Curve.mesh_cached = bpy.props.BoolProperty(name="Mesh Cached", description="No need to reexport curve data", default=False)
|
||||
bpy.types.Curve.dynamic_usage = bpy.props.BoolProperty(name="Dynamic Data Usage", description="Curve data can change at runtime", default=False)
|
||||
# For armature
|
||||
bpy.types.Armature.armature_cached = bpy.props.BoolProperty(name="Armature Cached", default=False)
|
||||
bpy.types.Armature.armature_cached = bpy.props.BoolProperty(name="Armature Cached", description="No need to reexport armature data", default=False)
|
||||
# Actions
|
||||
bpy.types.Armature.edit_actions = bpy.props.BoolProperty(name="Edit Actions", default=False)
|
||||
bpy.types.Armature.edit_actions = bpy.props.BoolProperty(name="Edit Actions", description="Manually set used actions", default=False)
|
||||
bpy.types.Armature.my_actiontraitlist = bpy.props.CollectionProperty(type=ListActionTraitItem)
|
||||
bpy.types.Armature.actiontraitlist_index = bpy.props.IntProperty(name="Index for my_list", default=0)
|
||||
bpy.types.Armature.actiontraitlist_index = bpy.props.IntProperty(name="Action index", default=0)
|
||||
# For camera
|
||||
bpy.types.Camera.frustum_culling = bpy.props.BoolProperty(name="Frustum Culling", default=True)
|
||||
bpy.types.Camera.renderpath_path = bpy.props.StringProperty(name="Render Path", default="deferred_path")
|
||||
bpy.types.Camera.renderpath_id = bpy.props.StringProperty(name="Render Path ID", default="deferred")
|
||||
bpy.types.Camera.frustum_culling = bpy.props.BoolProperty(name="Frustum Culling", description="Perform frustum culling for this camera", default=True)
|
||||
bpy.types.Camera.renderpath_path = bpy.props.StringProperty(name="Render Path", description="Render path nodes used for this camera", default="deferred_path")
|
||||
bpy.types.Camera.renderpath_id = bpy.props.StringProperty(name="Render Path ID", description="Asset ID", default="deferred")
|
||||
# TODO: Specify multiple material ids, merge ids from multiple cameras
|
||||
bpy.types.Camera.renderpath_passes = bpy.props.StringProperty(name="Render Path Passes", default="")
|
||||
bpy.types.Camera.renderpath_passes = bpy.props.StringProperty(name="Render Path Passes", description="Referenced render passes", default="")
|
||||
bpy.types.Camera.mesh_context = bpy.props.StringProperty(name="Mesh", default="mesh")
|
||||
bpy.types.Camera.mesh_context_empty = bpy.props.StringProperty(name="Mesh Empty", default="depthwrite")
|
||||
bpy.types.Camera.shadows_context = bpy.props.StringProperty(name="Shadows", default="shadowmap")
|
||||
bpy.types.Camera.translucent_context = bpy.props.StringProperty(name="Translucent", default="translucent")
|
||||
bpy.types.Camera.overlay_context = bpy.props.StringProperty(name="Overlay", default="overlay")
|
||||
bpy.types.Camera.is_probe = bpy.props.BoolProperty(name="Probe", default=False)
|
||||
bpy.types.Camera.probe_generate_radiance = bpy.props.BoolProperty(name="Generate Radiance", default=False)
|
||||
bpy.types.Camera.is_probe = bpy.props.BoolProperty(name="Probe", description="Render this camera as environment probe using Cycles", default=False)
|
||||
bpy.types.Camera.probe_generate_radiance = bpy.props.BoolProperty(name="Generate Radiance", description="Generate radiance textures", default=False)
|
||||
bpy.types.Camera.probe_texture = bpy.props.StringProperty(name="Texture", default="")
|
||||
bpy.types.Camera.probe_num_mips = bpy.props.IntProperty(name="Number of mips", default=0)
|
||||
bpy.types.Camera.probe_volume = bpy.props.StringProperty(name="Volume", default="")
|
||||
bpy.types.Camera.probe_strength = bpy.props.FloatProperty(name="Strength", default=1.0)
|
||||
bpy.types.Camera.probe_blending = bpy.props.FloatProperty(name="Blending", default=0.0)
|
||||
bpy.types.Camera.is_mirror = bpy.props.BoolProperty(name="Mirror", default=False)
|
||||
bpy.types.Camera.is_mirror = bpy.props.BoolProperty(name="Mirror", description="Render this camera into texture", default=False)
|
||||
bpy.types.Camera.mirror_resolution_x = bpy.props.FloatProperty(name="X", default=512.0)
|
||||
bpy.types.Camera.mirror_resolution_y = bpy.props.FloatProperty(name="Y", default=256.0)
|
||||
bpy.types.Camera.last_decal_context = bpy.props.StringProperty(name="Decal Context", default='')
|
||||
|
@ -308,7 +349,7 @@ def initProperties():
|
|||
bpy.types.World.generate_fog_amounta = bpy.props.FloatProperty(name="Amount A", default=0.25, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_fog_amountb = bpy.props.FloatProperty(name="Amount B", default=0.5, update=invalidate_shader_cache)
|
||||
# Skin
|
||||
bpy.types.World.generate_gpu_skin = bpy.props.BoolProperty(name="GPU Skinning", default=True, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_gpu_skin = bpy.props.BoolProperty(name="GPU Skinning", description="Calculate skinning on GPU", default=True, update=invalidate_shader_cache)
|
||||
bpy.types.World.generate_gpu_skin_max_bones = bpy.props.IntProperty(name="Max Bones", default=50, min=1, max=84, update=invalidate_shader_cache)
|
||||
# Material override flags
|
||||
bpy.types.World.force_no_culling = bpy.props.BoolProperty(name="Force No Culling", default=False)
|
||||
|
@ -342,12 +383,12 @@ def initProperties():
|
|||
('False', 'False', 'False')],
|
||||
name = "Depth-Write", default='True')
|
||||
# For scene
|
||||
bpy.types.Scene.game_export = bpy.props.BoolProperty(name="Export", default=True)
|
||||
bpy.types.Scene.game_export = bpy.props.BoolProperty(name="Export", description="Export scene data", default=True)
|
||||
# For lamp
|
||||
bpy.types.Lamp.lamp_clip_start = bpy.props.FloatProperty(name="Clip Start", default=0.1)
|
||||
bpy.types.Lamp.lamp_clip_end = bpy.props.FloatProperty(name="Clip End", default=50.0)
|
||||
bpy.types.Lamp.lamp_fov = bpy.props.FloatProperty(name="FoV", default=0.785)
|
||||
bpy.types.Lamp.lamp_shadows_bias = bpy.props.FloatProperty(name="Shadows Bias", default=0.0001)
|
||||
bpy.types.Lamp.lamp_fov = bpy.props.FloatProperty(name="Field of View", default=0.785)
|
||||
bpy.types.Lamp.lamp_shadows_bias = bpy.props.FloatProperty(name="Shadows Bias", description="Depth offset for shadow acne", default=0.0001)
|
||||
|
||||
# Menu in object region
|
||||
class ObjectPropsPanel(bpy.types.Panel):
|
||||
|
@ -362,7 +403,9 @@ class ObjectPropsPanel(bpy.types.Panel):
|
|||
if obj == None:
|
||||
return
|
||||
|
||||
if bpy.data.worlds['Arm'].ArmExportHideRender == False:
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
|
||||
if wrd.ArmExportHideRender == False:
|
||||
layout.prop(obj, 'hide_render')
|
||||
hide = obj.hide_render
|
||||
else:
|
||||
|
@ -372,71 +415,73 @@ class ObjectPropsPanel(bpy.types.Panel):
|
|||
if hide:
|
||||
return
|
||||
|
||||
layout.prop(obj, 'spawn')
|
||||
layout.prop(obj, 'game_visible')
|
||||
layout.prop(obj, 'mobile')
|
||||
if obj.type == 'MESH':
|
||||
layout.prop(obj, 'instanced_children')
|
||||
if obj.instanced_children:
|
||||
layout.label('Location')
|
||||
row = layout.row()
|
||||
row.prop(obj, 'instanced_children_loc_x')
|
||||
row.prop(obj, 'instanced_children_loc_y')
|
||||
row.prop(obj, 'instanced_children_loc_z')
|
||||
layout.label('Rotation')
|
||||
row = layout.row()
|
||||
row.prop(obj, 'instanced_children_rot_x')
|
||||
row.prop(obj, 'instanced_children_rot_y')
|
||||
row.prop(obj, 'instanced_children_rot_z')
|
||||
layout.label('Scale')
|
||||
row = layout.row()
|
||||
row.prop(obj, 'instanced_children_scale_x')
|
||||
row.prop(obj, 'instanced_children_scale_y')
|
||||
row.prop(obj, 'instanced_children_scale_z')
|
||||
layout.prop(obj, 'override_material')
|
||||
if obj.override_material:
|
||||
layout.prop(obj, 'override_material_name')
|
||||
|
||||
if obj.type == 'ARMATURE':
|
||||
layout.prop(obj, 'bone_animation_enabled')
|
||||
if obj.bone_animation_enabled:
|
||||
layout.prop(obj, 'edit_actions_prop')
|
||||
if obj.edit_actions_prop:
|
||||
layout.prop_search(obj, "start_action_name_prop", obj.data, "my_actiontraitlist", "Start Action")
|
||||
else:
|
||||
layout.prop(obj, 'object_animation_enabled')
|
||||
|
||||
if (obj.type == 'ARMATURE' and obj.bone_animation_enabled) or (obj.type != 'ARMATURE' and obj.object_animation_enabled):
|
||||
layout.prop(obj, 'edit_tracks_prop')
|
||||
if obj.edit_tracks_prop:
|
||||
layout.prop_search(obj, "start_track_name_prop", obj, "my_cliptraitlist", "Start Clip")
|
||||
# Tracks list
|
||||
layout.label("Clips")
|
||||
animrow = layout.row()
|
||||
animrows = 2
|
||||
if len(obj.my_cliptraitlist) > 1:
|
||||
animrows = 4
|
||||
|
||||
row = layout.row()
|
||||
row.template_list("MY_UL_ClipTraitList", "The_List", obj, "my_cliptraitlist", obj, "cliptraitlist_index", rows=animrows)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("my_cliptraitlist.new_item", icon='ZOOMIN', text="")
|
||||
col.operator("my_cliptraitlist.delete_item", icon='ZOOMOUT', text="")
|
||||
|
||||
if len(obj.my_cliptraitlist) > 1:
|
||||
col.separator()
|
||||
col.operator("my_cliptraitlist.move_item", icon='TRIA_UP', text="").direction = 'UP'
|
||||
col.operator("my_cliptraitlist.move_item", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
if obj.cliptraitlist_index >= 0 and len(obj.my_cliptraitlist) > 0:
|
||||
animitem = obj.my_cliptraitlist[obj.cliptraitlist_index]
|
||||
layout.prop(wrd, 'ArmObjectAdvanced')
|
||||
if wrd.ArmObjectAdvanced:
|
||||
layout.prop(obj, 'spawn')
|
||||
layout.prop(obj, 'game_visible')
|
||||
layout.prop(obj, 'mobile')
|
||||
if obj.type == 'MESH':
|
||||
layout.prop(obj, 'instanced_children')
|
||||
if obj.instanced_children:
|
||||
layout.label('Location')
|
||||
row = layout.row()
|
||||
row.prop(animitem, "start_prop")
|
||||
row.prop(animitem, "end_prop")
|
||||
layout.prop(animitem, "speed_prop")
|
||||
layout.prop(animitem, "loop_prop")
|
||||
layout.prop(animitem, "reflect_prop")
|
||||
row.prop(obj, 'instanced_children_loc_x')
|
||||
row.prop(obj, 'instanced_children_loc_y')
|
||||
row.prop(obj, 'instanced_children_loc_z')
|
||||
layout.label('Rotation')
|
||||
row = layout.row()
|
||||
row.prop(obj, 'instanced_children_rot_x')
|
||||
row.prop(obj, 'instanced_children_rot_y')
|
||||
row.prop(obj, 'instanced_children_rot_z')
|
||||
layout.label('Scale')
|
||||
row = layout.row()
|
||||
row.prop(obj, 'instanced_children_scale_x')
|
||||
row.prop(obj, 'instanced_children_scale_y')
|
||||
row.prop(obj, 'instanced_children_scale_z')
|
||||
layout.prop(obj, 'override_material')
|
||||
if obj.override_material:
|
||||
layout.prop(obj, 'override_material_name')
|
||||
|
||||
if obj.type == 'ARMATURE':
|
||||
layout.prop(obj, 'bone_animation_enabled')
|
||||
if obj.bone_animation_enabled:
|
||||
layout.prop(obj, 'edit_actions_prop')
|
||||
if obj.edit_actions_prop:
|
||||
layout.prop_search(obj, "start_action_name_prop", obj.data, "my_actiontraitlist", "Start Action")
|
||||
else:
|
||||
layout.prop(obj, 'object_animation_enabled')
|
||||
|
||||
if (obj.type == 'ARMATURE' and obj.bone_animation_enabled) or (obj.type != 'ARMATURE' and obj.object_animation_enabled):
|
||||
layout.prop(obj, 'edit_tracks_prop')
|
||||
if obj.edit_tracks_prop:
|
||||
layout.prop_search(obj, "start_track_name_prop", obj, "my_cliptraitlist", "Start Clip")
|
||||
# Tracks list
|
||||
layout.label("Clips")
|
||||
animrow = layout.row()
|
||||
animrows = 2
|
||||
if len(obj.my_cliptraitlist) > 1:
|
||||
animrows = 4
|
||||
|
||||
row = layout.row()
|
||||
row.template_list("MY_UL_ClipTraitList", "The_List", obj, "my_cliptraitlist", obj, "cliptraitlist_index", rows=animrows)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("my_cliptraitlist.new_item", icon='ZOOMIN', text="")
|
||||
col.operator("my_cliptraitlist.delete_item", icon='ZOOMOUT', text="")
|
||||
|
||||
if len(obj.my_cliptraitlist) > 1:
|
||||
col.separator()
|
||||
col.operator("my_cliptraitlist.move_item", icon='TRIA_UP', text="").direction = 'UP'
|
||||
col.operator("my_cliptraitlist.move_item", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
if obj.cliptraitlist_index >= 0 and len(obj.my_cliptraitlist) > 0:
|
||||
animitem = obj.my_cliptraitlist[obj.cliptraitlist_index]
|
||||
row = layout.row()
|
||||
row.prop(animitem, "start_prop")
|
||||
row.prop(animitem, "end_prop")
|
||||
layout.prop(animitem, "speed_prop")
|
||||
layout.prop(animitem, "loop_prop")
|
||||
layout.prop(animitem, "reflect_prop")
|
||||
|
||||
# Menu in modifiers region
|
||||
class ModifiersPropsPanel(bpy.types.Panel):
|
||||
|
@ -486,13 +531,16 @@ class DataPropsPanel(bpy.types.Panel):
|
|||
layout.prop_search(obj.data, "renderpath_path", bpy.data, "node_groups")
|
||||
layout.operator("arm.reimport_paths_menu")
|
||||
elif obj.type == 'MESH' or obj.type == 'FONT':
|
||||
layout.prop(obj.data, 'static_usage')
|
||||
layout.prop(obj.data, 'dynamic_usage')
|
||||
layout.operator("arm.invalidate_cache")
|
||||
elif obj.type == 'LAMP':
|
||||
layout.prop(obj.data, 'lamp_clip_start')
|
||||
layout.prop(obj.data, 'lamp_clip_end')
|
||||
layout.prop(obj.data, 'lamp_fov')
|
||||
layout.prop(obj.data, 'lamp_shadows_bias')
|
||||
elif obj.type == 'SPEAKER':
|
||||
layout.prop(obj.data, 'loop')
|
||||
layout.prop(obj.data, 'stream')
|
||||
elif obj.type == 'ARMATURE':
|
||||
layout.prop(obj.data, 'edit_actions')
|
||||
if obj.data.edit_actions:
|
||||
|
@ -543,6 +591,7 @@ class ReimportPathsMenu(bpy.types.Menu):
|
|||
layout.operator("arm.reimport_paths")
|
||||
|
||||
class ReimportPathsButton(bpy.types.Operator):
|
||||
'''Reimport default render paths'''
|
||||
bl_label = "Reimport Paths"
|
||||
bl_idname = "arm.reimport_paths_menu"
|
||||
|
||||
|
@ -551,14 +600,16 @@ class ReimportPathsButton(bpy.types.Operator):
|
|||
return {"FINISHED"}
|
||||
|
||||
class OBJECT_OT_REIMPORTPATHSButton(bpy.types.Operator):
|
||||
'''Reimport default render paths'''
|
||||
bl_idname = "arm.reimport_paths"
|
||||
bl_label = "Reimport Paths"
|
||||
|
||||
def execute(self, context):
|
||||
nodes_renderpath.load_library()
|
||||
make_renderpath.load_library()
|
||||
return{'FINISHED'}
|
||||
|
||||
class OBJECT_OT_INVALIDATECACHEButton(bpy.types.Operator):
|
||||
'''Delete cached mesh data'''
|
||||
bl_idname = "arm.invalidate_cache"
|
||||
bl_label = "Invalidate Cache"
|
||||
|
||||
|
@ -700,11 +751,14 @@ class ArmoryPlayPanel(bpy.types.Panel):
|
|||
if wrd.ArmPlayViewportCamera:
|
||||
layout.prop(wrd, 'ArmPlayViewportNavigation')
|
||||
|
||||
layout.prop(wrd, 'ArmPlayConsole')
|
||||
layout.prop(wrd, 'ArmPlayDeveloperTools')
|
||||
layout.prop(wrd, 'ArmPlayLivePatch')
|
||||
if wrd.ArmPlayLivePatch:
|
||||
layout.prop(wrd, 'ArmPlayAutoBuild')
|
||||
layout.prop(wrd, 'ArmPlayAdvanced')
|
||||
if wrd.ArmPlayAdvanced:
|
||||
layout.prop(wrd, 'ArmPlayConsole')
|
||||
# layout.prop(wrd, 'ArmPlayDeveloperTools')
|
||||
if utils.with_chromium():
|
||||
layout.prop(wrd, 'ArmPlayLivePatch')
|
||||
if wrd.ArmPlayLivePatch:
|
||||
layout.prop(wrd, 'ArmPlayAutoBuild')
|
||||
|
||||
class ArmoryBuildPanel(bpy.types.Panel):
|
||||
bl_label = "Armory Build"
|
||||
|
@ -723,18 +777,21 @@ class ArmoryBuildPanel(bpy.types.Panel):
|
|||
layout.operator("arm.kode_studio")
|
||||
layout.operator("arm.clean")
|
||||
layout.prop(wrd, 'ArmProjectTarget')
|
||||
layout.prop(wrd, 'ArmCacheShaders')
|
||||
layout.prop(wrd, 'ArmMinimize')
|
||||
layout.prop(wrd, 'ArmOptimizeMesh')
|
||||
layout.prop(wrd, 'ArmSampledAnimation')
|
||||
layout.prop(wrd, 'ArmDeinterleavedBuffers')
|
||||
layout.prop(wrd, 'generate_gpu_skin')
|
||||
if wrd.generate_gpu_skin:
|
||||
layout.prop(wrd, 'generate_gpu_skin_max_bones')
|
||||
layout.prop(wrd, 'ArmProjectSamplesPerPixel')
|
||||
layout.label('Libraries')
|
||||
layout.prop(wrd, 'ArmPhysics')
|
||||
layout.prop(wrd, 'ArmNavigation')
|
||||
layout.prop(wrd, 'ArmBuildAdvanced')
|
||||
if wrd.ArmBuildAdvanced:
|
||||
layout.prop(wrd, 'ArmCacheShaders')
|
||||
layout.prop(wrd, 'ArmCleanEnvmaps')
|
||||
layout.prop(wrd, 'ArmMinimize')
|
||||
layout.prop(wrd, 'ArmOptimizeMesh')
|
||||
layout.prop(wrd, 'ArmSampledAnimation')
|
||||
layout.prop(wrd, 'ArmDeinterleavedBuffers')
|
||||
layout.prop(wrd, 'generate_gpu_skin')
|
||||
if wrd.generate_gpu_skin:
|
||||
layout.prop(wrd, 'generate_gpu_skin_max_bones')
|
||||
layout.prop(wrd, 'ArmProjectSamplesPerPixel')
|
||||
layout.label('Libraries')
|
||||
layout.prop(wrd, 'ArmPhysics')
|
||||
layout.prop(wrd, 'ArmNavigation')
|
||||
|
||||
class ArmoryProjectPanel(bpy.types.Panel):
|
||||
bl_label = "Armory Project"
|
||||
|
@ -743,6 +800,7 @@ class ArmoryProjectPanel(bpy.types.Panel):
|
|||
bl_context = "render"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
info_text = ''
|
||||
progress = 100.0
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -750,18 +808,21 @@ class ArmoryProjectPanel(bpy.types.Panel):
|
|||
layout.prop(wrd, 'ArmProjectName')
|
||||
layout.prop(wrd, 'ArmProjectPackage')
|
||||
layout.prop_search(wrd, 'ArmKhafile', bpy.data, 'texts', 'Khafile')
|
||||
layout.prop(wrd, 'ArmPlayActiveScene')
|
||||
if wrd.ArmPlayActiveScene == False:
|
||||
layout.prop_search(wrd, 'ArmProjectScene', bpy.data, 'scenes', 'Scene')
|
||||
layout.prop(wrd, 'ArmExportHideRender')
|
||||
layout.prop(wrd, 'ArmSpawnAllLayers')
|
||||
layout.label('Publish Project')
|
||||
layout.operator('arm.publish')
|
||||
layout.prop(wrd, 'ArmPublishTarget')
|
||||
layout.label('Armory v' + wrd.ArmVersion)
|
||||
layout.operator('arm.check_updates')
|
||||
|
||||
layout.prop(wrd, 'ArmProjectAdvanced')
|
||||
if wrd.ArmProjectAdvanced:
|
||||
layout.prop(wrd, 'ArmPlayActiveScene')
|
||||
if wrd.ArmPlayActiveScene == False:
|
||||
layout.prop_search(wrd, 'ArmProjectScene', bpy.data, 'scenes', 'Scene')
|
||||
layout.prop(wrd, 'ArmExportHideRender')
|
||||
layout.prop(wrd, 'ArmSpawnAllLayers')
|
||||
layout.label('Armory v' + wrd.ArmVersion)
|
||||
layout.operator('arm.check_updates')
|
||||
|
||||
class ArmoryPlayButton(bpy.types.Operator):
|
||||
'''Launch player in new window'''
|
||||
bl_idname = 'arm.play'
|
||||
bl_label = 'Play'
|
||||
|
||||
|
@ -772,6 +833,7 @@ class ArmoryPlayButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryPlayInViewportButton(bpy.types.Operator):
|
||||
'''Launch player in 3D viewport'''
|
||||
bl_idname = 'arm.play_in_viewport'
|
||||
bl_label = 'Play in Viewport'
|
||||
|
||||
|
@ -792,6 +854,7 @@ class ArmoryPlayInViewportButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryStopButton(bpy.types.Operator):
|
||||
'''Stop currently running player'''
|
||||
bl_idname = 'arm.stop'
|
||||
bl_label = 'Stop'
|
||||
|
||||
|
@ -800,17 +863,19 @@ class ArmoryStopButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryBuildButton(bpy.types.Operator):
|
||||
'''Build and compile project'''
|
||||
bl_idname = 'arm.build'
|
||||
bl_label = 'Build'
|
||||
|
||||
def execute(self, context):
|
||||
invalidate_shader_cache.enabled = False
|
||||
make.build_project()
|
||||
make.compile_project()
|
||||
make.compile_project(watch=True)
|
||||
invalidate_shader_cache.enabled = True
|
||||
return{'FINISHED'}
|
||||
|
||||
class ArmoryPatchButton(bpy.types.Operator):
|
||||
'''Update currently running player instance'''
|
||||
bl_idname = 'arm.patch'
|
||||
bl_label = 'Live Patch'
|
||||
|
||||
|
@ -822,6 +887,7 @@ class ArmoryPatchButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryFolderButton(bpy.types.Operator):
|
||||
'''Open project folder'''
|
||||
bl_idname = 'arm.folder'
|
||||
bl_label = 'Project Folder'
|
||||
|
||||
|
@ -830,6 +896,7 @@ class ArmoryFolderButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryCheckUpdatesButton(bpy.types.Operator):
|
||||
'''Open a website in the web-browser'''
|
||||
bl_idname = 'arm.check_updates'
|
||||
bl_label = 'Check for Updates'
|
||||
|
||||
|
@ -838,6 +905,7 @@ class ArmoryCheckUpdatesButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryKodeStudioButton(bpy.types.Operator):
|
||||
'''Launch this project in Kode Studio'''
|
||||
bl_idname = 'arm.kode_studio'
|
||||
bl_label = 'Kode Studio'
|
||||
bl_description = 'Open Project in Kode Studio'
|
||||
|
@ -860,6 +928,7 @@ class ArmoryKodeStudioButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryCleanButton(bpy.types.Operator):
|
||||
'''Delete all cached data'''
|
||||
bl_idname = 'arm.clean'
|
||||
bl_label = 'Clean'
|
||||
|
||||
|
@ -868,8 +937,9 @@ class ArmoryCleanButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryPublishButton(bpy.types.Operator):
|
||||
'''Build project ready for publishing'''
|
||||
bl_idname = 'arm.publish'
|
||||
bl_label = 'Publish'
|
||||
bl_label = 'Publish Project'
|
||||
|
||||
def execute(self, context):
|
||||
make.publish_project()
|
||||
|
@ -887,6 +957,9 @@ def draw_play_item(self, context):
|
|||
# Info panel in header
|
||||
def draw_info_item(self, context):
|
||||
layout = self.layout
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
if wrd.ArmProgress < 100:
|
||||
layout.prop(wrd, 'ArmProgress')
|
||||
if ArmoryProjectPanel.info_text != '':
|
||||
layout.label(ArmoryProjectPanel.info_text)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import shutil
|
|||
import bpy
|
||||
import os
|
||||
import json
|
||||
from traits_params import *
|
||||
from props_traits_params import *
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from bpy.props import *
|
||||
import utils
|
||||
|
@ -154,6 +154,7 @@ class LIST_OT_TraitMoveItem(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryEditScriptButton(bpy.types.Operator):
|
||||
'''Edit script in Kode Studio'''
|
||||
bl_idname = 'arm.edit_script'
|
||||
bl_label = 'Edit Script'
|
||||
|
||||
|
@ -174,6 +175,7 @@ class ArmoryEditScriptButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmoryNewScriptDialog(bpy.types.Operator):
|
||||
'''Create blank script'''
|
||||
bl_idname = "arm.new_script"
|
||||
bl_label = "New Script"
|
||||
|
||||
|
@ -193,6 +195,7 @@ class ArmoryNewScriptDialog(bpy.types.Operator):
|
|||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
class ArmoryRefreshScriptsListButton(bpy.types.Operator):
|
||||
'''Fetch all script names'''
|
||||
bl_idname = 'arm.refresh_scripts_list'
|
||||
bl_label = 'Refresh Scripts List'
|
||||
|
||||
|
@ -289,7 +292,6 @@ class ToolsTraitsPanel(bpy.types.Panel):
|
|||
row = layout.row()
|
||||
row.prop_search(item, "nodes_name_prop", bpy.data, "node_groups", "Tree")
|
||||
|
||||
# Registration
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
initObjectProperties()
|
|
@ -7,7 +7,6 @@ import make
|
|||
|
||||
class SPACEARMORY_HT_header(Header):
|
||||
bl_space_type = 'VIEW_GAME'
|
||||
|
||||
info_text = ''
|
||||
is_paused = False
|
||||
|
||||
|
@ -28,17 +27,21 @@ class SPACEARMORY_HT_header(Header):
|
|||
layout.label(SPACEARMORY_HT_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 = make.play_project.play_area
|
||||
area.type = 'VIEW_3D'
|
||||
SPACEARMORY_HT_header.is_paused = False
|
||||
SPACEARMORY_HT_header.info_text = ''
|
||||
return{'FINISHED'}
|
||||
|
||||
class ArmorySpacePauseButton(bpy.types.Operator):
|
||||
'''Pause rendering'''
|
||||
bl_idname = 'arm.space_pause'
|
||||
bl_label = 'Pause'
|
||||
|
||||
|
@ -47,6 +50,7 @@ class ArmorySpacePauseButton(bpy.types.Operator):
|
|||
return{'FINISHED'}
|
||||
|
||||
class ArmorySpaceResumeButton(bpy.types.Operator):
|
||||
'''Resume rendering'''
|
||||
bl_idname = 'arm.space_resume'
|
||||
bl_label = 'Resume'
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import make
|
||||
import nodes_logic
|
||||
import nodes_renderpath
|
||||
import nodes_world
|
||||
import exporter
|
||||
import traits_action
|
||||
import traits_clip
|
||||
import traits_params
|
||||
import traits
|
||||
import props_traits_action
|
||||
import props_traits_clip
|
||||
import props_traits_params
|
||||
import props_traits
|
||||
import props
|
||||
import space_armory
|
||||
import utils
|
||||
|
@ -14,16 +13,15 @@ import lib.drop_to_ground
|
|||
|
||||
def register():
|
||||
utils.register()
|
||||
traits_action.register()
|
||||
traits_clip.register()
|
||||
props_traits_action.register()
|
||||
props_traits_clip.register()
|
||||
props.register()
|
||||
make.register()
|
||||
nodes_logic.register()
|
||||
nodes_renderpath.register()
|
||||
nodes_world.register()
|
||||
exporter.register()
|
||||
traits_params.register()
|
||||
traits.register()
|
||||
props_traits_params.register()
|
||||
props_traits.register()
|
||||
space_armory.register()
|
||||
lib.drop_to_ground.register()
|
||||
|
||||
|
@ -32,12 +30,11 @@ def unregister():
|
|||
make.unregister()
|
||||
nodes_logic.unregister()
|
||||
nodes_renderpath.unregister()
|
||||
nodes_world.unregister()
|
||||
exporter.unregister()
|
||||
traits_params.unregister()
|
||||
traits.unregister()
|
||||
props_traits_params.unregister()
|
||||
props_traits.unregister()
|
||||
props.unregister()
|
||||
traits_action.unregister()
|
||||
traits_clip.unregister()
|
||||
props_traits_action.unregister()
|
||||
props_traits_clip.unregister()
|
||||
space_armory.unregister()
|
||||
lib.drop_to_ground.unregister()
|
||||
|
|
|
@ -37,8 +37,8 @@ project.addShaders('Sources/Shaders/**');
|
|||
f.write(add_armory_library(sdk_path + '/lib/', 'haxebullet'))
|
||||
|
||||
# Electron live patching
|
||||
if is_play and bpy.data.worlds['Arm'].ArmPlayLivePatch == True and bpy.data.worlds['Arm'].ArmPlayRuntime == 'Electron':
|
||||
f.write("project.addDefine('WITH_PATCH_ELECTRON');\n")
|
||||
# if is_play and bpy.data.worlds['Arm'].ArmPlayLivePatch == True and bpy.data.worlds['Arm'].ArmPlayRuntime == 'Electron':
|
||||
# f.write("project.addDefine('WITH_PATCH_ELECTRON');\n")
|
||||
|
||||
# Native scripting
|
||||
# f.write(add_armory_library(sdk_path + '/lib/', 'haxeduktape'))
|
||||
|
@ -83,7 +83,7 @@ project.addShaders('Sources/Shaders/**');
|
|||
f.write("\n\nresolve(project);\n")
|
||||
|
||||
# Write Main.hx
|
||||
def write_main():
|
||||
def write_main(is_play, in_viewport):
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
resx, resy = utils.get_render_resolution()
|
||||
#if not os.path.isfile('Sources/Main.hx'):
|
||||
|
@ -99,9 +99,9 @@ class Main {
|
|||
static inline var projectSamplesPerPixel = """ + str(wrd.ArmProjectSamplesPerPixel) + """;
|
||||
static inline var projectScene = '""" + utils.get_project_scene_name() + """';
|
||||
public static function main() {
|
||||
iron.sys.CompileTime.importPackage('armory.trait');
|
||||
iron.sys.CompileTime.importPackage('armory.renderpath');
|
||||
iron.sys.CompileTime.importPackage('""" + wrd.ArmProjectPackage + """');
|
||||
iron.system.CompileTime.importPackage('armory.trait');
|
||||
iron.system.CompileTime.importPackage('armory.renderpath');
|
||||
iron.system.CompileTime.importPackage('""" + wrd.ArmProjectPackage + """');
|
||||
#if (js && WITH_PHYSICS)
|
||||
untyped __js__("
|
||||
function loadScript(url, callback) {
|
||||
|
@ -127,7 +127,11 @@ class Main {
|
|||
f.write("""
|
||||
kha.System.init({title: projectName, width: projectWidth, height: projectHeight, samplesPerPixel: projectSamplesPerPixel}, function() {
|
||||
iron.App.init(function() {
|
||||
iron.Scene.setActive(projectScene, function(object:iron.object.Object) {
|
||||
iron.Scene.setActive(projectScene, function(object:iron.object.Object) {""")
|
||||
if utils.with_chromium() and in_viewport and is_play:
|
||||
f.write("""
|
||||
object.addTrait(new armory.trait.internal.EditorSpace());""")
|
||||
f.write("""
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -49,7 +49,9 @@ uniform vec4 baseCol;
|
|||
uniform float skinBones[skinMaxBones * 8]; // Dual quat
|
||||
#endif
|
||||
#ifdef _Probes
|
||||
uniform mat4 W; // TODO: Conflicts with _HeightTex
|
||||
#ifndef _HeightTex
|
||||
uniform mat4 W;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Veloc
|
||||
uniform mat4 prevWVP;
|
||||
|
@ -182,14 +184,15 @@ void main() {
|
|||
#endif
|
||||
|
||||
#ifdef _Billboard
|
||||
mat4 constrWV = WV;
|
||||
// Spherical
|
||||
WV[0][0] = 1.0; WV[0][1] = 0.0; WV[0][2] = 0.0;
|
||||
WV[1][0] = 0.0; WV[1][1] = 1.0; WV[1][2] = 0.0;
|
||||
WV[2][0] = 0.0; WV[2][1] = 0.0; WV[2][2] = 1.0;
|
||||
constrWV[0][0] = 1.0; constrWV[0][1] = 0.0; constrWV[0][2] = 0.0;
|
||||
constrWV[1][0] = 0.0; constrWV[1][1] = 1.0; constrWV[1][2] = 0.0;
|
||||
constrWV[2][0] = 0.0; constrWV[2][1] = 0.0; constrWV[2][2] = 1.0;
|
||||
// Cylindrical
|
||||
//WV[0][0] = 1.0; WV[0][1] = 0.0; WV[0][2] = 0.0;
|
||||
//WV[2][0] = 0.0; WV[2][1] = 0.0; WV[2][2] = 1.0;
|
||||
gl_Position = P * WV * sPos;
|
||||
//constrWV[0][0] = 1.0; constrWV[0][1] = 0.0; constrWV[0][2] = 0.0;
|
||||
//constrWV[2][0] = 0.0; constrWV[2][1] = 0.0; constrWV[2][2] = 1.0;
|
||||
gl_Position = P * constrWV * sPos;
|
||||
#else
|
||||
gl_Position = WVP * sPos;
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,10 @@ in vec3 nor;
|
|||
#endif
|
||||
|
||||
uniform mat4 WVP;
|
||||
#ifdef _Billboard
|
||||
uniform mat4 WV;
|
||||
uniform mat4 P;
|
||||
#endif
|
||||
#ifdef _Skinning
|
||||
uniform float skinBones[skinMaxBones * 8];
|
||||
#endif
|
||||
|
@ -94,5 +98,17 @@ void main() {
|
|||
sPos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz)); // Translate
|
||||
#endif
|
||||
|
||||
#ifdef _Billboard
|
||||
mat4 constrWV = WV;
|
||||
// Spherical
|
||||
constrWV[0][0] = 1.0; constrWV[0][1] = 0.0; constrWV[0][2] = 0.0;
|
||||
constrWV[1][0] = 0.0; constrWV[1][1] = 1.0; constrWV[1][2] = 0.0;
|
||||
constrWV[2][0] = 0.0; constrWV[2][1] = 0.0; constrWV[2][2] = 1.0;
|
||||
// Cylindrical
|
||||
//constrWV[0][0] = 1.0; constrWV[0][1] = 0.0; constrWV[0][2] = 0.0;
|
||||
//constrWV[2][0] = 0.0; constrWV[2][1] = 0.0; constrWV[2][2] = 1.0;
|
||||
gl_Position = P * constrWV * sPos;
|
||||
#else
|
||||
gl_Position = WVP * sPos;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -26,12 +26,14 @@
|
|||
"link": "_normalMatrix"
|
||||
},
|
||||
{
|
||||
"name": "V",
|
||||
"link": "_viewMatrix"
|
||||
"name": "WV",
|
||||
"link": "_worldViewMatrix",
|
||||
"ifdef": ["_Billboard"]
|
||||
},
|
||||
{
|
||||
"name": "P",
|
||||
"link": "_projectionMatrix"
|
||||
"link": "_projectionMatrix",
|
||||
"ifdef": ["_Billboard"]
|
||||
},
|
||||
{
|
||||
"name": "WVP",
|
||||
|
@ -276,6 +278,16 @@
|
|||
"name": "WVP",
|
||||
"link": "_worldViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "P",
|
||||
"link": "_projectionMatrix",
|
||||
"ifdef": ["_Billboard"]
|
||||
},
|
||||
{
|
||||
"name": "WV",
|
||||
"link": "_worldViewMatrix",
|
||||
"ifdef": ["_Billboard"]
|
||||
},
|
||||
{
|
||||
"name": "skinBones",
|
||||
"link": "_skinBones",
|
||||
|
|
|
@ -27,8 +27,10 @@ in vec3 nor;
|
|||
|
||||
uniform mat4 W;
|
||||
uniform mat4 N;
|
||||
uniform mat4 V;
|
||||
uniform mat4 P;
|
||||
#ifdef _Billboard
|
||||
uniform mat4 WV;
|
||||
uniform mat4 P;
|
||||
#endif
|
||||
uniform mat4 WVP;
|
||||
uniform mat4 LWVP;
|
||||
uniform vec4 baseCol;
|
||||
|
@ -120,20 +122,19 @@ void main() {
|
|||
|
||||
lPos = LWVP * sPos;
|
||||
|
||||
mat4 WV = V * W;
|
||||
|
||||
#ifdef _Billboard
|
||||
mat4 constrWV = WV;
|
||||
// Spherical
|
||||
WV[0][0] = 1.0; WV[0][1] = 0.0; WV[0][2] = 0.0;
|
||||
WV[1][0] = 0.0; WV[1][1] = 1.0; WV[1][2] = 0.0;
|
||||
WV[2][0] = 0.0; WV[2][1] = 0.0; WV[2][2] = 1.0;
|
||||
constrWV[0][0] = 1.0; constrWV[0][1] = 0.0; constrWV[0][2] = 0.0;
|
||||
constrWV[1][0] = 0.0; constrWV[1][1] = 1.0; constrWV[1][2] = 0.0;
|
||||
constrWV[2][0] = 0.0; constrWV[2][1] = 0.0; constrWV[2][2] = 1.0;
|
||||
// Cylindrical
|
||||
//WV[0][0] = 1.0; WV[0][1] = 0.0; WV[0][2] = 0.0;
|
||||
//WV[2][0] = 0.0; WV[2][1] = 0.0; WV[2][2] = 1.0;
|
||||
#endif
|
||||
|
||||
// gl_Position = P * WV * sPos;
|
||||
//constrWV[0][0] = 1.0; constrWV[0][1] = 0.0; constrWV[0][2] = 0.0;
|
||||
//constrWV[2][0] = 0.0; constrWV[2][1] = 0.0; constrWV[2][2] = 1.0;
|
||||
gl_Position = P * constrWV * sPos;
|
||||
#else
|
||||
gl_Position = WVP * sPos;
|
||||
#endif
|
||||
|
||||
#ifdef _Tex
|
||||
texCoord = tex;
|
||||
|
|
Loading…
Reference in a new issue