merge upstream
This commit is contained in:
		@ -775,6 +775,7 @@ class Scene {
 | 
				
			|||||||
			// Attach particle systems
 | 
								// Attach particle systems
 | 
				
			||||||
			#if lnx_particles
 | 
								#if lnx_particles
 | 
				
			||||||
			if (o.particle_refs != null) {
 | 
								if (o.particle_refs != null) {
 | 
				
			||||||
 | 
									cast(object, MeshObject).render_emitter = o.render_emitter;
 | 
				
			||||||
				for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref);
 | 
									for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			#end
 | 
								#end
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										50
									
								
								leenkx/Sources/iron/format/bmp/Data.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								leenkx/Sources/iron/format/bmp/Data.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * format - Haxe File Formats
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  BMP File Format
 | 
				
			||||||
 | 
					 *  Copyright (C) 2007-2009 Trevor McCauley, Baluta Cristian (hx port) & Robert Sköld (format conversion)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2009, The Haxe Project Contributors
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   - Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *     notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   - Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *     notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *     documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
				
			||||||
 | 
					 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
				
			||||||
 | 
					 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
				
			||||||
 | 
					 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
				
			||||||
 | 
					 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 | 
				
			||||||
 | 
					 * DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					package iron.format.bmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef Data = {
 | 
				
			||||||
 | 
					    var header : iron.format.bmp.Header;
 | 
				
			||||||
 | 
					    var pixels : haxe.io.Bytes;
 | 
				
			||||||
 | 
					#if (haxe_ver < 4)
 | 
				
			||||||
 | 
					    var colorTable : Null<haxe.io.Bytes>;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    var ?colorTable : haxe.io.Bytes;
 | 
				
			||||||
 | 
					#end
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef Header = {
 | 
				
			||||||
 | 
					    var width : Int;          // real width (in pixels)
 | 
				
			||||||
 | 
					    var height : Int;         // real height (in pixels)
 | 
				
			||||||
 | 
					    var paddedStride : Int;   // number of bytes in a stride (including padding)
 | 
				
			||||||
 | 
					    var topToBottom : Bool;   // whether the bitmap is stored top to bottom
 | 
				
			||||||
 | 
					    var bpp : Int;            // bits per pixel
 | 
				
			||||||
 | 
					    var dataLength : Int;     // equal to `paddedStride` * `height`
 | 
				
			||||||
 | 
					    var compression : Int;    // which compression is being used, 0 for no compression
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										122
									
								
								leenkx/Sources/iron/format/bmp/Reader.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								leenkx/Sources/iron/format/bmp/Reader.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * format - Haxe File Formats
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  BMP File Format
 | 
				
			||||||
 | 
					 *  Copyright (C) 2007-2009 Robert Sköld
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2009, The Haxe Project Contributors
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   - Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *     notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   - Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *     notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *     documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
				
			||||||
 | 
					 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
				
			||||||
 | 
					 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
				
			||||||
 | 
					 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
				
			||||||
 | 
					 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 | 
				
			||||||
 | 
					 * DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package iron.format.bmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.format.bmp.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Reader {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var input : haxe.io.Input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new( i ) {
 | 
				
			||||||
 | 
							input = i;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** 
 | 
				
			||||||
 | 
						 * Only supports uncompressed 24bpp bitmaps (the most common format).
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * The returned bytes in `Data.pixels` will be in BGR order, and with padding (if present).
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @see https://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx
 | 
				
			||||||
 | 
						 * @see https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function read() : format.bmp.Data {
 | 
				
			||||||
 | 
							// Read Header
 | 
				
			||||||
 | 
							for (b in ["B".code, "M".code]) {
 | 
				
			||||||
 | 
								if (input.readByte() != b) throw "Invalid header";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							var fileSize = input.readInt32();
 | 
				
			||||||
 | 
							input.readInt32();							// Reserved
 | 
				
			||||||
 | 
							var offset = input.readInt32();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Read InfoHeader
 | 
				
			||||||
 | 
							var infoHeaderSize = input.readInt32();		// InfoHeader size
 | 
				
			||||||
 | 
							if (infoHeaderSize != 40) {
 | 
				
			||||||
 | 
								throw 'Info headers with size $infoHeaderSize not supported.';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var width = input.readInt32();				// Image width (actual, not padded)
 | 
				
			||||||
 | 
							var height = input.readInt32();				// Image height
 | 
				
			||||||
 | 
							var numPlanes = input.readInt16();			// Number of planes
 | 
				
			||||||
 | 
							var bits = input.readInt16();				// Bits per pixel
 | 
				
			||||||
 | 
							var compression = input.readInt32();		// Compression type
 | 
				
			||||||
 | 
							var dataLength = input.readInt32();			// Image data size (includes padding!)
 | 
				
			||||||
 | 
							input.readInt32();							// Horizontal resolution
 | 
				
			||||||
 | 
							input.readInt32();							// Vertical resolution
 | 
				
			||||||
 | 
							var colorsUsed = input.readInt32();			// Colors used (0 when uncompressed)
 | 
				
			||||||
 | 
							input.readInt32();							// Important colors (0 when uncompressed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// If there's no compression, the dataLength may be 0
 | 
				
			||||||
 | 
							if ( compression == 0 && dataLength == 0 ) dataLength = fileSize - offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var bytesRead = 54; // total read above
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							var colorTable : haxe.io.Bytes = null;
 | 
				
			||||||
 | 
							if ( bits <= 8 ) {
 | 
				
			||||||
 | 
								if ( colorsUsed == 0 ) {
 | 
				
			||||||
 | 
									colorsUsed = Tools.getNumColorsForBitDepth(bits);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var colorTableLength = 4 * colorsUsed;
 | 
				
			||||||
 | 
								colorTable = haxe.io.Bytes.alloc( colorTableLength );
 | 
				
			||||||
 | 
								input.readFullBytes( colorTable, 0, colorTableLength );
 | 
				
			||||||
 | 
								bytesRead += colorTableLength;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							input.read( offset - bytesRead );
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							var p = haxe.io.Bytes.alloc( dataLength );	
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// Read Raster Data
 | 
				
			||||||
 | 
							var paddedStride = Tools.computePaddedStride(width, bits);
 | 
				
			||||||
 | 
							var topToBottom = false;
 | 
				
			||||||
 | 
							if ( height < 0 ) { // if bitmap is stored top to bottom
 | 
				
			||||||
 | 
								topToBottom = true;
 | 
				
			||||||
 | 
								height = -height;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
							input.readFullBytes(p, 0, dataLength);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								header: {
 | 
				
			||||||
 | 
									width: width,
 | 
				
			||||||
 | 
									height: height,
 | 
				
			||||||
 | 
									paddedStride: paddedStride,
 | 
				
			||||||
 | 
									topToBottom: topToBottom,
 | 
				
			||||||
 | 
									bpp: bits,
 | 
				
			||||||
 | 
									dataLength: dataLength,
 | 
				
			||||||
 | 
									compression: compression
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								pixels: p,
 | 
				
			||||||
 | 
								colorTable: colorTable
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										256
									
								
								leenkx/Sources/iron/format/bmp/Tools.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								leenkx/Sources/iron/format/bmp/Tools.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,256 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * format - Haxe File Formats
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  BMP File Format
 | 
				
			||||||
 | 
					 *  Copyright (C) 2007-2009 Trevor McCauley, Baluta Cristian (hx port) & Robert Sköld (format conversion)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2009, The Haxe Project Contributors
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   - Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *     notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   - Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *     notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *     documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
				
			||||||
 | 
					 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
				
			||||||
 | 
					 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
				
			||||||
 | 
					 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
				
			||||||
 | 
					 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 | 
				
			||||||
 | 
					 * DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					package iron.format.bmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Tools {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//												  a  r  g  b
 | 
				
			||||||
 | 
						static var ARGB_MAP(default, never):Array<Int> = [0, 1, 2, 3];
 | 
				
			||||||
 | 
						static var BGRA_MAP(default, never):Array<Int> = [3, 2, 1, 0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static var COLOR_SIZE(default, never):Int = 4;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
							Extract BMP pixel data (24bpp in BGR format) and expands it to BGRA, removing any padding in the process.
 | 
				
			||||||
 | 
						**/
 | 
				
			||||||
 | 
						inline static public function extractBGRA( bmp : iron.format.bmp.Data ) : haxe.io.Bytes {
 | 
				
			||||||
 | 
							return _extract32(bmp, BGRA_MAP, 0xFF);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
							Extract BMP pixel data (24bpp in BGR format) and converts it to ARGB.
 | 
				
			||||||
 | 
						**/
 | 
				
			||||||
 | 
						inline static public function extractARGB( bmp : iron.format.bmp.Data ) : haxe.io.Bytes {
 | 
				
			||||||
 | 
							return _extract32(bmp, ARGB_MAP, 0xFF);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
							Creates BMP data from bytes in BGRA format for each pixel.
 | 
				
			||||||
 | 
						**/
 | 
				
			||||||
 | 
						inline static public function buildFromBGRA( width : Int, height : Int, srcBytes : haxe.io.Bytes, topToBottom : Bool = false ) : Data {
 | 
				
			||||||
 | 
							return _buildFrom32(width, height, srcBytes, BGRA_MAP, topToBottom);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
							Creates BMP data from bytes in ARGB format for each pixel.
 | 
				
			||||||
 | 
						**/
 | 
				
			||||||
 | 
						inline static public function buildFromARGB( width : Int, height : Int, srcBytes : haxe.io.Bytes, topToBottom : Bool = false ) : Data {
 | 
				
			||||||
 | 
							return _buildFrom32(width, height, srcBytes, ARGB_MAP, topToBottom);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline static public function computePaddedStride(width:Int, bpp:Int):Int {
 | 
				
			||||||
 | 
							return ((((width * bpp) + 31) & ~31) >> 3);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Gets number of colors for indexed palettes
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						inline static public function getNumColorsForBitDepth(bpp:Int):Int {
 | 
				
			||||||
 | 
							return switch (bpp) {
 | 
				
			||||||
 | 
								case 1: 2;
 | 
				
			||||||
 | 
								case 4: 16;
 | 
				
			||||||
 | 
								case 8: 256;
 | 
				
			||||||
 | 
								case 16: 65536;
 | 
				
			||||||
 | 
								default: throw 'Unsupported bpp $bpp';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// `channelMap` contains indices to map into ARGB (f.e. the mapping for ARGB is [0,1,2,3], while for BGRA is [3,2,1,0])
 | 
				
			||||||
 | 
						static function _extract32( bmp : iron.format.bmp.Data, channelMap : Array<Int>, alpha : Int = 0xFF) : haxe.io.Bytes {
 | 
				
			||||||
 | 
							var srcBytes = bmp.pixels;
 | 
				
			||||||
 | 
							var dstLen = bmp.header.width * bmp.header.height * 4;
 | 
				
			||||||
 | 
							var dstBytes = haxe.io.Bytes.alloc( dstLen );
 | 
				
			||||||
 | 
							var srcPaddedStride = bmp.header.paddedStride;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							var yDir = -1;
 | 
				
			||||||
 | 
							var dstPos = 0;
 | 
				
			||||||
 | 
							var srcPos = srcPaddedStride * (bmp.header.height - 1);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
							if ( bmp.header.topToBottom ) {
 | 
				
			||||||
 | 
								yDir = 1;
 | 
				
			||||||
 | 
								srcPos = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( bmp.header.bpp < 8 || bmp.header.bpp == 16 ) {
 | 
				
			||||||
 | 
								throw 'bpp ${bmp.header.bpp} not supported';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var colorTable:haxe.io.Bytes = null;
 | 
				
			||||||
 | 
							if ( bmp.header.bpp <= 8 ) {
 | 
				
			||||||
 | 
								var colorTableLength = getNumColorsForBitDepth(bmp.header.bpp);
 | 
				
			||||||
 | 
								colorTable = haxe.io.Bytes.alloc(colorTableLength * COLOR_SIZE);
 | 
				
			||||||
 | 
								var definedColorTableLength = Std.int( bmp.colorTable.length / COLOR_SIZE );
 | 
				
			||||||
 | 
								for( i in 0...definedColorTableLength ) {
 | 
				
			||||||
 | 
									var b = bmp.colorTable.get( i * COLOR_SIZE);
 | 
				
			||||||
 | 
									var g = bmp.colorTable.get( i * COLOR_SIZE + 1);
 | 
				
			||||||
 | 
									var r = bmp.colorTable.get( i * COLOR_SIZE + 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									colorTable.set(i * COLOR_SIZE + channelMap[0], alpha);
 | 
				
			||||||
 | 
									colorTable.set(i * COLOR_SIZE + channelMap[1], r);
 | 
				
			||||||
 | 
									colorTable.set(i * COLOR_SIZE + channelMap[2], g);
 | 
				
			||||||
 | 
									colorTable.set(i * COLOR_SIZE + channelMap[3], b);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// We want to have the table the full length in case indices outside the range are present
 | 
				
			||||||
 | 
								colorTable.fill(definedColorTableLength, colorTableLength - definedColorTableLength, 0);
 | 
				
			||||||
 | 
								for( i in definedColorTableLength...colorTableLength ) {
 | 
				
			||||||
 | 
									colorTable.set(i * COLOR_SIZE + channelMap[0], alpha);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch bmp.header.compression {
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									while( dstPos < dstLen ) {
 | 
				
			||||||
 | 
										for( i in 0...bmp.header.width ) {
 | 
				
			||||||
 | 
											if (bmp.header.bpp == 8) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												var currentSrcPos = srcPos + i;
 | 
				
			||||||
 | 
												var index = srcBytes.get(currentSrcPos);
 | 
				
			||||||
 | 
												dstBytes.blit( dstPos, colorTable, index * COLOR_SIZE, COLOR_SIZE );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											} else if (bmp.header.bpp == 24) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												var currentSrcPos = srcPos + i * 3;
 | 
				
			||||||
 | 
												var b = srcBytes.get(currentSrcPos);
 | 
				
			||||||
 | 
												var g = srcBytes.get(currentSrcPos + 1);
 | 
				
			||||||
 | 
												var r = srcBytes.get(currentSrcPos + 2);
 | 
				
			||||||
 | 
												
 | 
				
			||||||
 | 
												dstBytes.set(dstPos + channelMap[0], alpha);
 | 
				
			||||||
 | 
												dstBytes.set(dstPos + channelMap[1], r);
 | 
				
			||||||
 | 
												dstBytes.set(dstPos + channelMap[2], g);
 | 
				
			||||||
 | 
												dstBytes.set(dstPos + channelMap[3], b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											} else if (bmp.header.bpp == 32) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												var currentSrcPos = srcPos + i * 4;
 | 
				
			||||||
 | 
												var b = srcBytes.get(currentSrcPos);
 | 
				
			||||||
 | 
												var g = srcBytes.get(currentSrcPos + 1);
 | 
				
			||||||
 | 
												var r = srcBytes.get(currentSrcPos + 2);
 | 
				
			||||||
 | 
												
 | 
				
			||||||
 | 
												dstBytes.set(dstPos + channelMap[0], alpha);
 | 
				
			||||||
 | 
												dstBytes.set(dstPos + channelMap[1], r);
 | 
				
			||||||
 | 
												dstBytes.set(dstPos + channelMap[2], g);
 | 
				
			||||||
 | 
												dstBytes.set(dstPos + channelMap[3], b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											dstPos += 4;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										srcPos += yDir * srcPaddedStride;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									srcPos = 0;
 | 
				
			||||||
 | 
									var x = 0;
 | 
				
			||||||
 | 
									var y = bmp.header.topToBottom ? 0 : bmp.header.height - 1;
 | 
				
			||||||
 | 
									while( srcPos < bmp.header.dataLength ) {
 | 
				
			||||||
 | 
										var count = srcBytes.get(srcPos++);
 | 
				
			||||||
 | 
										var index = srcBytes.get(srcPos++);
 | 
				
			||||||
 | 
										if ( count == 0 ) {
 | 
				
			||||||
 | 
											if ( index == 0 ) {
 | 
				
			||||||
 | 
												x = 0;
 | 
				
			||||||
 | 
												y += yDir;
 | 
				
			||||||
 | 
											} else if ( index == 1 ) {
 | 
				
			||||||
 | 
												break;
 | 
				
			||||||
 | 
											} else if ( index == 2 ) {
 | 
				
			||||||
 | 
												x += srcBytes.get(srcPos++);
 | 
				
			||||||
 | 
												y += srcBytes.get(srcPos++);
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												count = index;
 | 
				
			||||||
 | 
												for( i in 0...count ) {
 | 
				
			||||||
 | 
													index = srcBytes.get(srcPos++);
 | 
				
			||||||
 | 
													dstBytes.blit( COLOR_SIZE * ((x+i) + y * bmp.header.width), colorTable, index * COLOR_SIZE, COLOR_SIZE );
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												if (srcPos % 2 != 0) srcPos++;
 | 
				
			||||||
 | 
												x += count;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											for( i in 0...count ) {
 | 
				
			||||||
 | 
												dstBytes.blit( COLOR_SIZE * ((x+i) + y * bmp.header.width), colorTable, index * COLOR_SIZE, COLOR_SIZE );
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											x += count;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									throw 'compression ${bmp.header.compression} not supported';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return dstBytes;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// `channelMap` contains indices to map into ARGB (f.e. the mapping for ARGB is [0,1,2,3], while for BGRA is [3,2,1,0])
 | 
				
			||||||
 | 
						static function _buildFrom32( width : Int, height : Int, srcBytes : haxe.io.Bytes, channelMap : Array<Int>, topToBottom : Bool = false ) : Data {
 | 
				
			||||||
 | 
							var bpp = 24;
 | 
				
			||||||
 | 
							var paddedStride = computePaddedStride(width, bpp);
 | 
				
			||||||
 | 
							var bytesBGR = haxe.io.Bytes.alloc(paddedStride * height);
 | 
				
			||||||
 | 
							var topToBottom = topToBottom;
 | 
				
			||||||
 | 
							var dataLength = bytesBGR.length;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							var dstStride = width * 3;
 | 
				
			||||||
 | 
							var srcLen = width * height * 4;
 | 
				
			||||||
 | 
							var yDir = -1;
 | 
				
			||||||
 | 
							var dstPos = dataLength - paddedStride;
 | 
				
			||||||
 | 
							var srcPos = 0;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if ( topToBottom ) {
 | 
				
			||||||
 | 
								yDir = 1;
 | 
				
			||||||
 | 
								dstPos = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							while( srcPos < srcLen ) {
 | 
				
			||||||
 | 
								var i = dstPos;
 | 
				
			||||||
 | 
								while( i < dstPos + dstStride ) {
 | 
				
			||||||
 | 
									var r = srcBytes.get(srcPos + channelMap[1]);
 | 
				
			||||||
 | 
									var g = srcBytes.get(srcPos + channelMap[2]);
 | 
				
			||||||
 | 
									var b = srcBytes.get(srcPos + channelMap[3]);
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									bytesBGR.set(i++, b);
 | 
				
			||||||
 | 
									bytesBGR.set(i++, g);
 | 
				
			||||||
 | 
									bytesBGR.set(i++, r);
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									srcPos += 4;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								dstPos += yDir * paddedStride;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								header: {
 | 
				
			||||||
 | 
									width: width,
 | 
				
			||||||
 | 
									height: height,
 | 
				
			||||||
 | 
									paddedStride: paddedStride,
 | 
				
			||||||
 | 
									topToBottom: topToBottom,
 | 
				
			||||||
 | 
									bpp: bpp,
 | 
				
			||||||
 | 
									dataLength: dataLength,
 | 
				
			||||||
 | 
									compression: 0
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								pixels: bytesBGR,
 | 
				
			||||||
 | 
								colorTable: null
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										74
									
								
								leenkx/Sources/iron/format/bmp/Writer.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								leenkx/Sources/iron/format/bmp/Writer.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * format - Haxe File Formats
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  BMP File Format
 | 
				
			||||||
 | 
					 *  Copyright (C) 2007-2009 Robert Sköld
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2009, The Haxe Project Contributors
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   - Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *     notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *   - Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *     notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *     documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
				
			||||||
 | 
					 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 | 
				
			||||||
 | 
					 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
				
			||||||
 | 
					 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
				
			||||||
 | 
					 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 | 
				
			||||||
 | 
					 * DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package iron.format.bmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.format.bmp.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Writer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static var DATA_OFFSET : Int = 0x36;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var output : haxe.io.Output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(o) {
 | 
				
			||||||
 | 
							output = o;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Specs: http://s223767089.online.de/en/file-format-bmp
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function write( bmp : Data ) {
 | 
				
			||||||
 | 
							// Write Header (14 bytes)
 | 
				
			||||||
 | 
							output.writeString( "BM" );								// Signature
 | 
				
			||||||
 | 
							output.writeInt32(bmp.pixels.length + DATA_OFFSET );	// FileSize
 | 
				
			||||||
 | 
							output.writeInt32( 0 );									// Reserved
 | 
				
			||||||
 | 
							output.writeInt32( DATA_OFFSET );						// Offset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Write InfoHeader (40 bytes)
 | 
				
			||||||
 | 
							output.writeInt32( 40 );								// InfoHeader size
 | 
				
			||||||
 | 
							output.writeInt32( bmp.header.width );					// Image width
 | 
				
			||||||
 | 
							var height = bmp.header.height;
 | 
				
			||||||
 | 
							if (bmp.header.topToBottom) height = -height; 
 | 
				
			||||||
 | 
							output.writeInt32( height );							// Image height
 | 
				
			||||||
 | 
							output.writeInt16( 1 );									// Number of planes
 | 
				
			||||||
 | 
							output.writeInt16( 24 );								// Bits per pixel (24bit RGB)
 | 
				
			||||||
 | 
							output.writeInt32( 0 );									// Compression type (no compression)
 | 
				
			||||||
 | 
							output.writeInt32( bmp.header.dataLength );				// Image data size (0 when uncompressed)
 | 
				
			||||||
 | 
							output.writeInt32( 0x2e30 );							// Horizontal resolution
 | 
				
			||||||
 | 
							output.writeInt32( 0x2e30 );							// Vertical resolution
 | 
				
			||||||
 | 
							output.writeInt32( 0 );									// Colors used (0 when uncompressed)
 | 
				
			||||||
 | 
							output.writeInt32( 0 );									// Important colors (0 when uncompressed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Write Raster Data
 | 
				
			||||||
 | 
							output.write(bmp.pixels);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -21,6 +21,7 @@ class MeshObject extends Object {
 | 
				
			|||||||
	public var particleChildren: Array<MeshObject> = null;
 | 
						public var particleChildren: Array<MeshObject> = null;
 | 
				
			||||||
	public var particleOwner: MeshObject = null; // Particle object
 | 
						public var particleOwner: MeshObject = null; // Particle object
 | 
				
			||||||
	public var particleIndex = -1;
 | 
						public var particleIndex = -1;
 | 
				
			||||||
 | 
						public var render_emitter = true;
 | 
				
			||||||
	#end
 | 
						#end
 | 
				
			||||||
	public var cameraDistance: Float;
 | 
						public var cameraDistance: Float;
 | 
				
			||||||
	public var screenSize = 0.0;
 | 
						public var screenSize = 0.0;
 | 
				
			||||||
@ -255,11 +256,11 @@ class MeshObject extends Object {
 | 
				
			|||||||
				particleSystems[i].update(particleChildren[i], this);
 | 
									particleSystems[i].update(particleChildren[i], this);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (particleSystems != null && particleSystems.length > 0 && !raw.render_emitter) return;
 | 
							if (particleSystems != null && particleSystems.length > 0 && !render_emitter) return;
 | 
				
			||||||
		#end
 | 
					        if (particleSystems == null && cullMaterial(context)) return;
 | 
				
			||||||
 | 
					        #else
 | 
				
			||||||
        if (cullMaterial(context)) return;
 | 
					        if (cullMaterial(context)) return;
 | 
				
			||||||
 | 
							#end
 | 
				
			||||||
		// Get lod
 | 
							// Get lod
 | 
				
			||||||
		var mats = materials;
 | 
							var mats = materials;
 | 
				
			||||||
		var lod = this;
 | 
							var lod = this;
 | 
				
			||||||
 | 
				
			|||||||
@ -18,29 +18,29 @@ class ParticleSystem {
 | 
				
			|||||||
	public var speed = 1.0;
 | 
						public var speed = 1.0;
 | 
				
			||||||
	var particles: Array<Particle>;
 | 
						var particles: Array<Particle>;
 | 
				
			||||||
	var ready: Bool;
 | 
						var ready: Bool;
 | 
				
			||||||
	var frameRate = 24;
 | 
						public var frameRate = 24;
 | 
				
			||||||
	var lifetime = 0.0;
 | 
						public var lifetime = 0.0;
 | 
				
			||||||
	var animtime = 0.0;
 | 
						public var animtime = 0.0;
 | 
				
			||||||
	var time = 0.0;
 | 
						public var time = 0.0;
 | 
				
			||||||
	var spawnRate = 0.0;
 | 
						public var spawnRate = 0.0;
 | 
				
			||||||
	var seed = 0;
 | 
						var seed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var r: TParticleData;
 | 
						public var r: TParticleData;
 | 
				
			||||||
	var gx: Float;
 | 
						public var gx: Float;
 | 
				
			||||||
	var gy: Float;
 | 
						public var gy: Float;
 | 
				
			||||||
	var gz: Float;
 | 
						public var gz: Float;
 | 
				
			||||||
	var alignx: Float;
 | 
						public var alignx: Float;
 | 
				
			||||||
	var aligny: Float;
 | 
						public var aligny: Float;
 | 
				
			||||||
	var alignz: Float;
 | 
						public var alignz: Float;
 | 
				
			||||||
	var dimx: Float;
 | 
						var dimx: Float;
 | 
				
			||||||
	var dimy: Float;
 | 
						var dimy: Float;
 | 
				
			||||||
	var tilesx: Int;
 | 
						var tilesx: Int;
 | 
				
			||||||
	var tilesy: Int;
 | 
						var tilesy: Int;
 | 
				
			||||||
	var tilesFramerate: Int;
 | 
						var tilesFramerate: Int;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var count = 0;
 | 
						public var count = 0;
 | 
				
			||||||
	var lap = 0;
 | 
						public var lap = 0;
 | 
				
			||||||
	var lapTime = 0.0;
 | 
						public var lapTime = 0.0;
 | 
				
			||||||
	var m = Mat4.identity();
 | 
						var m = Mat4.identity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var ownerLoc = new Vec4();
 | 
						var ownerLoc = new Vec4();
 | 
				
			||||||
@ -149,7 +149,7 @@ class ParticleSystem {
 | 
				
			|||||||
		// GPU particles transform is attached to owner object
 | 
							// GPU particles transform is attached to owner object
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function setupGeomGpu(object: MeshObject, owner: MeshObject) {
 | 
						public function setupGeomGpu(object: MeshObject, owner: MeshObject) {
 | 
				
			||||||
		var instancedData = new Float32Array(particles.length * 6);
 | 
							var instancedData = new Float32Array(particles.length * 6);
 | 
				
			||||||
		var i = 0;
 | 
							var i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										99
									
								
								leenkx/Sources/leenkx/logicnode/AddParticleToObjectNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								leenkx/Sources/leenkx/logicnode/AddParticleToObjectNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.data.SceneFormat.TSceneFormat;
 | 
				
			||||||
 | 
					import iron.data.Data;
 | 
				
			||||||
 | 
					import iron.object.Object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddParticleToObjectNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public var property0: String;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree: LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function run(from: Int) {
 | 
				
			||||||
 | 
							#if lnx_particles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (property0 == 'Scene Active'){		
 | 
				
			||||||
 | 
								var objFrom: Object = inputs[1].get();
 | 
				
			||||||
 | 
								var slot: Int = inputs[2].get();
 | 
				
			||||||
 | 
								var objTo: Object = inputs[3].get();
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
								if (objFrom == null || objTo == null) return;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
								var mobjFrom = cast(objFrom, iron.object.MeshObject);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
								var psys = mobjFrom.particleSystems != null ? mobjFrom.particleSystems[slot] : 
 | 
				
			||||||
 | 
									mobjFrom.particleOwner != null && mobjFrom.particleOwner.particleSystems != null ? mobjFrom.particleOwner.particleSystems[slot] : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (psys == null) return;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
								var mobjTo = cast(objTo, iron.object.MeshObject);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
								mobjTo.setupParticleSystem(iron.Scene.active.raw.name, {name: 'LnxPS', seed: 0, particle: psys.r.name});
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								mobjTo.render_emitter = inputs[4].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								iron.Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
 | 
				
			||||||
 | 
									if (o != null) {
 | 
				
			||||||
 | 
										var c: iron.object.MeshObject = cast o;
 | 
				
			||||||
 | 
										if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
 | 
				
			||||||
 | 
										mobjTo.particleChildren.push(c);
 | 
				
			||||||
 | 
										c.particleOwner = mobjTo;
 | 
				
			||||||
 | 
										c.particleIndex = mobjTo.particleChildren.length - 1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
								var oslot: Int = mobjTo.particleSystems.length-1;
 | 
				
			||||||
 | 
								var opsys = mobjTo.particleSystems[oslot];
 | 
				
			||||||
 | 
								opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								var sceneName: String = inputs[1].get();
 | 
				
			||||||
 | 
								var objectName: String = inputs[2].get();
 | 
				
			||||||
 | 
								var slot: Int = inputs[3].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var mobjTo: Object = inputs[4].get();
 | 
				
			||||||
 | 
								var mobjTo = cast(mobjTo, iron.object.MeshObject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								#if lnx_json
 | 
				
			||||||
 | 
									sceneName += ".json";
 | 
				
			||||||
 | 
								#elseif lnx_compress
 | 
				
			||||||
 | 
									sceneName += ".lz4";
 | 
				
			||||||
 | 
								#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Data.getSceneRaw(sceneName, (rawScene: TSceneFormat) -> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (obj in rawScene.objects) {
 | 
				
			||||||
 | 
									if (obj.name == objectName) {
 | 
				
			||||||
 | 
										mobjTo.setupParticleSystem(sceneName, obj.particle_refs[slot]);
 | 
				
			||||||
 | 
										mobjTo.render_emitter = inputs[5].get();					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										iron.Scene.active.spawnObject(rawScene.particle_datas[slot].instance_object, null, function(o: Object) {
 | 
				
			||||||
 | 
											if (o != null) {
 | 
				
			||||||
 | 
												var c: iron.object.MeshObject = cast o;
 | 
				
			||||||
 | 
												if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
 | 
				
			||||||
 | 
												mobjTo.particleChildren.push(c);
 | 
				
			||||||
 | 
												c.particleOwner = mobjTo;
 | 
				
			||||||
 | 
												c.particleIndex = mobjTo.particleChildren.length - 1;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}, true, rawScene);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										var oslot: Int = mobjTo.particleSystems.length-1;
 | 
				
			||||||
 | 
										var opsys = mobjTo.particleSystems[oslot];
 | 
				
			||||||
 | 
										opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							runOutput(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2,6 +2,9 @@ package leenkx.logicnode;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import iron.Scene;
 | 
					import iron.Scene;
 | 
				
			||||||
import iron.object.CameraObject;
 | 
					import iron.object.CameraObject;
 | 
				
			||||||
 | 
					import iron.math.Vec4;
 | 
				
			||||||
 | 
					import iron.math.Quat;
 | 
				
			||||||
 | 
					import leenkx.math.Helper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import leenkx.renderpath.RenderPathCreator;
 | 
					import leenkx.renderpath.RenderPathCreator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,11 +30,19 @@ class DrawCameraTextureNode extends LogicNode {
 | 
				
			|||||||
				final c = inputs[2].get();
 | 
									final c = inputs[2].get();
 | 
				
			||||||
				assert(Error, Std.isOfType(c, CameraObject), "Camera must be a camera object!");
 | 
									assert(Error, Std.isOfType(c, CameraObject), "Camera must be a camera object!");
 | 
				
			||||||
				cam = cast(c, CameraObject);
 | 
									cam = cast(c, CameraObject);
 | 
				
			||||||
				rt = kha.Image.createRenderTarget(iron.App.w(), iron.App.h());
 | 
									rt = kha.Image.createRenderTarget(iron.App.w(), iron.App.h(),
 | 
				
			||||||
 | 
										kha.graphics4.TextureFormat.RGBA32,
 | 
				
			||||||
 | 
										kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				assert(Error, mo.materials[matSlot].contexts[0].textures != null, 'Object "${mo.name}" has no diffuse texture to render to');
 | 
									assert(Error, mo.materials[matSlot].contexts[0].textures != null, 'Object "${mo.name}" has no diffuse texture to render to');
 | 
				
			||||||
				mo.materials[matSlot].contexts[0].textures[0] = rt; // Override diffuse texture
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                final n = inputs[5].get();
 | 
				
			||||||
 | 
									for (i => node in mo.materials[matSlot].contexts[0].raw.bind_textures){
 | 
				
			||||||
 | 
										if (node.name == n){
 | 
				
			||||||
 | 
											mo.materials[matSlot].contexts[0].textures[i] = rt; // Override diffuse texture
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				tree.notifyOnRender(render);
 | 
									tree.notifyOnRender(render);
 | 
				
			||||||
				runOutput(0);
 | 
									runOutput(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,8 +59,20 @@ class DrawCameraTextureNode extends LogicNode {
 | 
				
			|||||||
		iron.Scene.active.camera = cam;
 | 
							iron.Scene.active.camera = cam;
 | 
				
			||||||
		cam.renderTarget = rt;
 | 
							cam.renderTarget = rt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							#if kha_html5
 | 
				
			||||||
 | 
							var q: Quat = new Quat();
 | 
				
			||||||
 | 
							q.fromAxisAngle(new Vec4(0, 0, 1, 1), Helper.degToRad(180));
 | 
				
			||||||
 | 
							cam.transform.rot.mult(q);
 | 
				
			||||||
 | 
							cam.transform.buildMatrix();
 | 
				
			||||||
 | 
							#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cam.renderFrame(g);
 | 
							cam.renderFrame(g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							#if kha_html5
 | 
				
			||||||
 | 
							cam.transform.rot.mult(q);
 | 
				
			||||||
 | 
							cam.transform.buildMatrix();
 | 
				
			||||||
 | 
							#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cam.renderTarget = oldRT;
 | 
							cam.renderTarget = oldRT;
 | 
				
			||||||
		iron.Scene.active.camera = sceneCam;
 | 
							iron.Scene.active.camera = sceneCam;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -99,8 +99,6 @@ class DrawImageSequenceNode extends LogicNode {
 | 
				
			|||||||
		final colorVec = inputs[4].get();
 | 
							final colorVec = inputs[4].get();
 | 
				
			||||||
		g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
 | 
							g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		trace(currentImgIdx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		g.drawScaledImage(images[currentImgIdx], inputs[5].get(), inputs[6].get(), inputs[7].get(), inputs[8].get());
 | 
							g.drawScaledImage(images[currentImgIdx], inputs[5].get(), inputs[6].get(), inputs[7].get(), inputs[8].get());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										59
									
								
								leenkx/Sources/leenkx/logicnode/DrawSubImageNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								leenkx/Sources/leenkx/logicnode/DrawSubImageNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.math.Vec4;
 | 
				
			||||||
 | 
					import kha.Image;
 | 
				
			||||||
 | 
					import kha.Color;
 | 
				
			||||||
 | 
					import leenkx.renderpath.RenderToTexture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DrawSubImageNode extends LogicNode {
 | 
				
			||||||
 | 
					    var img: Image;
 | 
				
			||||||
 | 
					    var lastImgName = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function new(tree: LogicTree) {
 | 
				
			||||||
 | 
					        super(tree);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override function run(from: Int) {
 | 
				
			||||||
 | 
					        RenderToTexture.ensure2DContext("DrawImageNode");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final imgName: String = inputs[1].get();
 | 
				
			||||||
 | 
					        final colorVec: Vec4 = inputs[2].get();
 | 
				
			||||||
 | 
					        final anchorH: Int = inputs[3].get();
 | 
				
			||||||
 | 
					        final anchorV: Int = inputs[4].get();
 | 
				
			||||||
 | 
					        final x: Float = inputs[5].get();
 | 
				
			||||||
 | 
					        final y: Float = inputs[6].get();
 | 
				
			||||||
 | 
					        final width: Float = inputs[7].get();
 | 
				
			||||||
 | 
					        final height: Float = inputs[8].get();
 | 
				
			||||||
 | 
					        final sx: Float = inputs[9].get();
 | 
				
			||||||
 | 
					        final sy: Float = inputs[10].get();
 | 
				
			||||||
 | 
					        final swidth: Float = inputs[11].get();
 | 
				
			||||||
 | 
					        final sheight: Float = inputs[12].get();
 | 
				
			||||||
 | 
					        final angle: Float = inputs[13].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final drawx = x - 0.5 * width * anchorH;
 | 
				
			||||||
 | 
					        final drawy = y - 0.5 * height * anchorV;
 | 
				
			||||||
 | 
					        final sdrawx = sx - 0.5 * swidth * anchorH;
 | 
				
			||||||
 | 
					        final sdrawy = sy - 0.5 * sheight * anchorV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        RenderToTexture.g.rotate(angle, x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (imgName != lastImgName) {
 | 
				
			||||||
 | 
					            // Load new image
 | 
				
			||||||
 | 
					            lastImgName = imgName;
 | 
				
			||||||
 | 
					            iron.data.Data.getImage(imgName, (image: Image) -> {
 | 
				
			||||||
 | 
					                img = image;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (img == null) {
 | 
				
			||||||
 | 
					            runOutput(0);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        RenderToTexture.g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
 | 
				
			||||||
 | 
					        RenderToTexture.g.drawScaledSubImage(img, sdrawx, sdrawy, swidth, sheight, drawx, drawy, width, height);
 | 
				
			||||||
 | 
					        RenderToTexture.g.rotate(-angle, x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        runOutput(0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										66
									
								
								leenkx/Sources/leenkx/logicnode/GetParticleDataNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								leenkx/Sources/leenkx/logicnode/GetParticleDataNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.object.Object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GetParticleDataNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree: LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function get(from: Int): Dynamic {
 | 
				
			||||||
 | 
							var object: Object = inputs[0].get();
 | 
				
			||||||
 | 
							var slot: Int = inputs[1].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (object == null) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#if lnx_particles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var mo = cast(object, iron.object.MeshObject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var psys = mo.particleSystems != null ? mo.particleSystems[slot] : 
 | 
				
			||||||
 | 
								mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (psys == null) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return switch (from) {
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									psys.r.name;
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									psys.r.particle_size;
 | 
				
			||||||
 | 
								case 2:
 | 
				
			||||||
 | 
									psys.r.frame_start;
 | 
				
			||||||
 | 
								case 3:
 | 
				
			||||||
 | 
									psys.r.frame_end;
 | 
				
			||||||
 | 
								case 4:
 | 
				
			||||||
 | 
									psys.lifetime;
 | 
				
			||||||
 | 
								case 5:
 | 
				
			||||||
 | 
									psys.r.lifetime;
 | 
				
			||||||
 | 
								case 6:
 | 
				
			||||||
 | 
									psys.r.emit_from;
 | 
				
			||||||
 | 
								case 7:
 | 
				
			||||||
 | 
									new iron.math.Vec3(psys.alignx*2, psys.aligny*2, psys.alignz*2);
 | 
				
			||||||
 | 
								case 8:
 | 
				
			||||||
 | 
									psys.r.factor_random;
 | 
				
			||||||
 | 
								case 9:
 | 
				
			||||||
 | 
									new iron.math.Vec3(psys.gx, psys.gy, psys.gz);
 | 
				
			||||||
 | 
								case 10:
 | 
				
			||||||
 | 
									psys.r.weight_gravity;
 | 
				
			||||||
 | 
								case 11:
 | 
				
			||||||
 | 
									psys.speed;
 | 
				
			||||||
 | 
								case 12:
 | 
				
			||||||
 | 
									psys.time;
 | 
				
			||||||
 | 
								case 13:
 | 
				
			||||||
 | 
									psys.lap;
 | 
				
			||||||
 | 
								case 14:
 | 
				
			||||||
 | 
									psys.lapTime;
 | 
				
			||||||
 | 
								case 15:
 | 
				
			||||||
 | 
									psys.count;
 | 
				
			||||||
 | 
								default: 
 | 
				
			||||||
 | 
									null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								leenkx/Sources/leenkx/logicnode/GetParticleNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								leenkx/Sources/leenkx/logicnode/GetParticleNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.object.Object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GetParticleNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree: LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function get(from: Int): Dynamic {
 | 
				
			||||||
 | 
							var object: Object = inputs[0].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (object == null) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#if lnx_particles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var mo = cast(object, iron.object.MeshObject);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							switch (from) {
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									var names: Array<String> = [];
 | 
				
			||||||
 | 
									if (mo.particleSystems != null)
 | 
				
			||||||
 | 
										for (psys in mo.particleSystems)
 | 
				
			||||||
 | 
											names.push(psys.r.name);
 | 
				
			||||||
 | 
									return names;
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									return mo.particleSystems != null ? mo.particleSystems.length : 0;
 | 
				
			||||||
 | 
								case 2:
 | 
				
			||||||
 | 
									return mo.render_emitter;
 | 
				
			||||||
 | 
								default: 
 | 
				
			||||||
 | 
									null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -18,7 +18,6 @@ class ProbabilisticOutputNode extends LogicNode {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sum > 1){
 | 
							if (sum > 1){
 | 
				
			||||||
			trace(sum);
 | 
					 | 
				
			||||||
			for (p in 0...probs.length)
 | 
								for (p in 0...probs.length)
 | 
				
			||||||
				probs[p] /= sum;
 | 
									probs[p] /= sum;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.object.Object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RemoveParticleFromObjectNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public var property0: String;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree: LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function run(from: Int) {
 | 
				
			||||||
 | 
							#if lnx_particles
 | 
				
			||||||
 | 
							var object: Object = inputs[1].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (object == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var mo = cast(object, iron.object.MeshObject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (mo.particleSystems == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (property0 == 'All'){
 | 
				
			||||||
 | 
								mo.particleSystems = null;
 | 
				
			||||||
 | 
								for (c in mo.particleChildren) c.remove();
 | 
				
			||||||
 | 
								mo.particleChildren = null;
 | 
				
			||||||
 | 
								mo.particleOwner = null;
 | 
				
			||||||
 | 
								mo.render_emitter = true;
 | 
				
			||||||
 | 
							} 
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								var slot: Int = -1;
 | 
				
			||||||
 | 
								if (property0 == 'Name'){
 | 
				
			||||||
 | 
									var name: String = inputs[2].get();
 | 
				
			||||||
 | 
									for (i => psys in mo.particleSystems){
 | 
				
			||||||
 | 
										if (psys.r.name == name){ slot = i; break; }
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} 
 | 
				
			||||||
 | 
								else slot = inputs[2].get();
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
								if (mo.particleSystems.length > slot){
 | 
				
			||||||
 | 
									for (i in slot+1...mo.particleSystems.length){
 | 
				
			||||||
 | 
										var mi = cast(mo.particleChildren[i], iron.object.MeshObject);
 | 
				
			||||||
 | 
										mi.particleIndex = mi.particleIndex - 1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									mo.particleSystems.splice(slot, 1);
 | 
				
			||||||
 | 
									mo.particleChildren[slot].remove();
 | 
				
			||||||
 | 
									mo.particleChildren.splice(slot, 1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (slot == 0){
 | 
				
			||||||
 | 
									mo.particleSystems = null;
 | 
				
			||||||
 | 
									mo.particleChildren = null;
 | 
				
			||||||
 | 
									mo.particleOwner = null;
 | 
				
			||||||
 | 
									mo.render_emitter = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							runOutput(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										75
									
								
								leenkx/Sources/leenkx/logicnode/SetParticleDataNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								leenkx/Sources/leenkx/logicnode/SetParticleDataNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.object.Object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SetParticleDataNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public var property0: String;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree: LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function run(from: Int) {
 | 
				
			||||||
 | 
							#if lnx_particles
 | 
				
			||||||
 | 
							var object: Object = inputs[1].get();
 | 
				
			||||||
 | 
							var slot: Int = inputs[2].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (object == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var mo = cast(object, iron.object.MeshObject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var psys = mo.particleSystems != null ? mo.particleSystems[slot] : 
 | 
				
			||||||
 | 
								mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null;		if (psys == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (property0) {
 | 
				
			||||||
 | 
								case 'Particle Size':
 | 
				
			||||||
 | 
									psys.r.particle_size = inputs[3].get();
 | 
				
			||||||
 | 
								case 'Frame Start':
 | 
				
			||||||
 | 
									psys.r.frame_start = inputs[3].get();
 | 
				
			||||||
 | 
									psys.animtime = (psys.r.frame_end - psys.r.frame_start) / psys.frameRate;
 | 
				
			||||||
 | 
									psys.spawnRate = ((psys.r.frame_end - psys.r.frame_start) / psys.count) / psys.frameRate;
 | 
				
			||||||
 | 
								case 'Frame End':
 | 
				
			||||||
 | 
									psys.r.frame_end = inputs[3].get();
 | 
				
			||||||
 | 
									psys.animtime = (psys.r.frame_end - psys.r.frame_start) / psys.frameRate;
 | 
				
			||||||
 | 
									psys.spawnRate = ((psys.r.frame_end - psys.r.frame_start) / psys.count) / psys.frameRate;
 | 
				
			||||||
 | 
								case 'Lifetime':
 | 
				
			||||||
 | 
									psys.lifetime = inputs[3].get() / psys.frameRate;
 | 
				
			||||||
 | 
								case 'Lifetime Random':
 | 
				
			||||||
 | 
									psys.r.lifetime_random = inputs[3].get();
 | 
				
			||||||
 | 
								case 'Emit From':
 | 
				
			||||||
 | 
									var emit_from: Int = inputs[3].get();
 | 
				
			||||||
 | 
									if (emit_from == 0 || emit_from == 1 || emit_from == 2) {
 | 
				
			||||||
 | 
										psys.r.emit_from = emit_from;
 | 
				
			||||||
 | 
										psys.setupGeomGpu(mo.particleChildren != null ? mo.particleChildren[slot] : cast(iron.Scene.active.getChild(psys.data.raw.instance_object), iron.object.MeshObject), mo);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case 'Velocity':
 | 
				
			||||||
 | 
									var vel: iron.math.Vec3 = inputs[3].get();
 | 
				
			||||||
 | 
									psys.alignx = vel.x / 2;
 | 
				
			||||||
 | 
									psys.aligny = vel.y / 2;
 | 
				
			||||||
 | 
									psys.alignz = vel.z / 2;
 | 
				
			||||||
 | 
								case 'Velocity Random':
 | 
				
			||||||
 | 
									psys.r.factor_random = inputs[3].get();
 | 
				
			||||||
 | 
								case 'Weight Gravity':
 | 
				
			||||||
 | 
									psys.r.weight_gravity = inputs[3].get();
 | 
				
			||||||
 | 
									if (iron.Scene.active.raw.gravity != null) {
 | 
				
			||||||
 | 
										psys.gx = iron.Scene.active.raw.gravity[0] * psys.r.weight_gravity;
 | 
				
			||||||
 | 
										psys.gy = iron.Scene.active.raw.gravity[1] * psys.r.weight_gravity;
 | 
				
			||||||
 | 
										psys.gz = iron.Scene.active.raw.gravity[2] * psys.r.weight_gravity;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										psys.gx = 0;
 | 
				
			||||||
 | 
										psys.gy = 0;
 | 
				
			||||||
 | 
										psys.gz = -9.81 * psys.r.weight_gravity;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case 'Speed':
 | 
				
			||||||
 | 
									psys.speed = inputs[3].get();
 | 
				
			||||||
 | 
								default: 
 | 
				
			||||||
 | 
									null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							runOutput(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.object.Object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SetParticleRenderEmitterNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree: LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function run(from: Int) {
 | 
				
			||||||
 | 
							#if lnx_particles
 | 
				
			||||||
 | 
							var object: Object = inputs[1].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (object == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cast(object, iron.object.MeshObject).render_emitter = inputs[2].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							#end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							runOutput(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -11,13 +11,16 @@ class SetParticleSpeedNode extends LogicNode {
 | 
				
			|||||||
	override function run(from: Int) {
 | 
						override function run(from: Int) {
 | 
				
			||||||
		#if lnx_particles
 | 
							#if lnx_particles
 | 
				
			||||||
		var object: Object = inputs[1].get();
 | 
							var object: Object = inputs[1].get();
 | 
				
			||||||
		var speed: Float = inputs[2].get();
 | 
							var slot: Int = inputs[2].get();
 | 
				
			||||||
 | 
							var speed: Float = inputs[3].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (object == null) return;
 | 
							if (object == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var mo = cast(object, iron.object.MeshObject);
 | 
							var mo = cast(object, iron.object.MeshObject);
 | 
				
			||||||
		var psys = mo.particleSystems.length > 0 ? mo.particleSystems[0] : null;
 | 
							var psys = mo.particleSystems != null ? mo.particleSystems[slot] : 
 | 
				
			||||||
		if (psys == null) mo.particleOwner.particleSystems[0];
 | 
								mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (psys == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		psys.speed = speed;
 | 
							psys.speed = speed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										105
									
								
								leenkx/Sources/leenkx/logicnode/WriteImageNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								leenkx/Sources/leenkx/logicnode/WriteImageNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import iron.object.CameraObject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class WriteImageNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var file: String;
 | 
				
			||||||
 | 
					    var camera: CameraObject;
 | 
				
			||||||
 | 
					    var renderTarget: kha.Image;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function new(tree: LogicTree) {
 | 
				
			||||||
 | 
					        super(tree);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override function run(from: Int) {
 | 
				
			||||||
 | 
					        // Relative or absolute path to file
 | 
				
			||||||
 | 
					        file = inputs[1].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert(Error, iron.App.w() % inputs[3].get() == 0 && iron.App.h() % inputs[4].get() == 0, "Aspect ratio must match display resolution ratio");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        camera = inputs[2].get();
 | 
				
			||||||
 | 
					        renderTarget = kha.Image.createRenderTarget(inputs[3].get(), inputs[4].get(),
 | 
				
			||||||
 | 
					            kha.graphics4.TextureFormat.RGBA32,
 | 
				
			||||||
 | 
					            kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tree.notifyOnRender(render);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function render(g: kha.graphics4.Graphics) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var ready = false;
 | 
				
			||||||
 | 
					        final sceneCam = iron.Scene.active.camera;
 | 
				
			||||||
 | 
					        final oldRT = camera.renderTarget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        iron.Scene.active.camera = camera;
 | 
				
			||||||
 | 
					        camera.renderTarget = renderTarget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        camera.renderFrame(g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var tex = camera.renderTarget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        camera.renderTarget = oldRT;
 | 
				
			||||||
 | 
					        iron.Scene.active.camera = sceneCam;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var pixels = tex.getPixels();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i in 0...pixels.length){
 | 
				
			||||||
 | 
					            if (pixels.get(i) != 0){ ready = true; break; }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //wait for getPixels ready
 | 
				
			||||||
 | 
					        if (ready) { 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var tx = inputs[5].get();
 | 
				
			||||||
 | 
					            var ty = inputs[6].get();
 | 
				
			||||||
 | 
					            var tw = inputs[7].get();
 | 
				
			||||||
 | 
					            var th = inputs[8].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var bo = new haxe.io.BytesOutput();
 | 
				
			||||||
 | 
					            var rgb = haxe.io.Bytes.alloc(tw * th * 4);
 | 
				
			||||||
 | 
					            for (j in ty...ty + th) {
 | 
				
			||||||
 | 
					                for (i in tx...tx + tw) {
 | 
				
			||||||
 | 
					                    var k = j * tex.width + i;
 | 
				
			||||||
 | 
					                    var m =  (j - ty) * tw + i - tx;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    #if kha_krom
 | 
				
			||||||
 | 
					                    var l = k;
 | 
				
			||||||
 | 
					                    #elseif kha_html5
 | 
				
			||||||
 | 
					                    var l = (tex.height - j) * tex.width + i;
 | 
				
			||||||
 | 
					                    #end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    //ARGB 0xff
 | 
				
			||||||
 | 
					                    rgb.set(m * 4 + 0, pixels.get(l * 4 + 3));
 | 
				
			||||||
 | 
					                    rgb.set(m * 4 + 1, pixels.get(l * 4 + 0)); 
 | 
				
			||||||
 | 
					                    rgb.set(m * 4 + 2, pixels.get(l * 4 + 1));
 | 
				
			||||||
 | 
					                    rgb.set(m * 4 + 3, pixels.get(l * 4 + 2));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var imgwriter = new iron.format.bmp.Writer(bo);
 | 
				
			||||||
 | 
					            imgwriter.write(iron.format.bmp.Tools.buildFromARGB(tw, th, rgb));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            #if kha_krom
 | 
				
			||||||
 | 
					            Krom.fileSaveBytes(Krom.getFilesLocation() +  "/" + file, bo.getBytes().getData());
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            #elseif kha_html5
 | 
				
			||||||
 | 
					            var blob = new js.html.Blob([bo.getBytes().getData()], {type: "application"});
 | 
				
			||||||
 | 
					            var url = js.html.URL.createObjectURL(blob);
 | 
				
			||||||
 | 
					            var a = cast(js.Browser.document.createElement("a"), js.html.AnchorElement);
 | 
				
			||||||
 | 
					            a.href = url;
 | 
				
			||||||
 | 
					            a.download = file;
 | 
				
			||||||
 | 
					            a.click();
 | 
				
			||||||
 | 
					            js.html.URL.revokeObjectURL(url);
 | 
				
			||||||
 | 
					            #end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            runOutput(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            tree.removeRender(render);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -191,7 +191,7 @@ def apply_materials(load_atlas=0):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                                mainNode = outputNode.inputs[0].links[0].from_node.inputs[0].links[0].from_node
 | 
					                                mainNode = outputNode.inputs[0].links[0].from_node.inputs[0].links[0].from_node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            if (mainNode.type == "ShaderNodeMixRGB"):
 | 
					                            if (mainNode.type == "ShaderNodeMix"):
 | 
				
			||||||
                                if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
					                                if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
				
			||||||
                                    print("Mix RGB shader found")
 | 
					                                    print("Mix RGB shader found")
 | 
				
			||||||
                                
 | 
					                                
 | 
				
			||||||
@ -199,9 +199,11 @@ def apply_materials(load_atlas=0):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                            #Add all nodes first
 | 
					                            #Add all nodes first
 | 
				
			||||||
                            #Add lightmap multipliction texture
 | 
					                            #Add lightmap multipliction texture
 | 
				
			||||||
                            mixNode = node_tree.nodes.new(type="ShaderNodeMixRGB")
 | 
					                            mixNode = node_tree.nodes.new(type="ShaderNodeMix")
 | 
				
			||||||
                            mixNode.name = "Lightmap_Multiplication"
 | 
					                            mixNode.name = "Lightmap_Multiplication"
 | 
				
			||||||
                            mixNode.location = -800, 300
 | 
					                            mixNode.location = -800, 300
 | 
				
			||||||
 | 
					                            mixNode.data_type = 'RGBA'
 | 
				
			||||||
 | 
					                            mixNode.inputs[0].default_value = 1
 | 
				
			||||||
                            if scene.TLM_EngineProperties.tlm_lighting_mode == "indirect" or scene.TLM_EngineProperties.tlm_lighting_mode == "indirectAO":
 | 
					                            if scene.TLM_EngineProperties.tlm_lighting_mode == "indirect" or scene.TLM_EngineProperties.tlm_lighting_mode == "indirectAO":
 | 
				
			||||||
                                mixNode.blend_type = 'MULTIPLY'
 | 
					                                mixNode.blend_type = 'MULTIPLY'
 | 
				
			||||||
                            else:
 | 
					                            else:
 | 
				
			||||||
@ -312,8 +314,8 @@ def apply_materials(load_atlas=0):
 | 
				
			|||||||
                                    else:
 | 
					                                    else:
 | 
				
			||||||
                                        mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
 | 
					                                        mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect decode node to mixnode
 | 
					                                    mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[6]) #Connect decode node to mixnode
 | 
				
			||||||
                                    mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect exposure node to mixnode
 | 
					                                    mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[6]) #Connect exposure node to mixnode
 | 
				
			||||||
                                
 | 
					                                
 | 
				
			||||||
                                else:
 | 
					                                else:
 | 
				
			||||||
                                    
 | 
					                                    
 | 
				
			||||||
@ -323,10 +325,10 @@ def apply_materials(load_atlas=0):
 | 
				
			|||||||
                                    else:
 | 
					                                    else:
 | 
				
			||||||
                                        mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
 | 
					                                        mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
 | 
					                                    mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
 | 
				
			||||||
                                
 | 
					                                
 | 
				
			||||||
                                mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
 | 
					                                mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[7]) #Connect basecolor to pbr node
 | 
				
			||||||
                                mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
 | 
					                                mat.node_tree.links.new(mixNode.outputs[2], mainNode.inputs[0]) #Connect mixnode to pbr node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                if not scene.TLM_EngineProperties.tlm_target == "vertex":
 | 
					                                if not scene.TLM_EngineProperties.tlm_target == "vertex":
 | 
				
			||||||
                                    mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
 | 
					                                    mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
 | 
				
			||||||
@ -338,11 +340,11 @@ def apply_materials(load_atlas=0):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                                if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
 | 
					                                if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
 | 
				
			||||||
                                    mat.node_tree.links.new(lightmapNode.outputs[0], ExposureNode.inputs[0]) #Connect lightmap node to mixnode
 | 
					                                    mat.node_tree.links.new(lightmapNode.outputs[0], ExposureNode.inputs[0]) #Connect lightmap node to mixnode
 | 
				
			||||||
                                    mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
 | 
					                                    mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
 | 
				
			||||||
                                else:
 | 
					                                else:
 | 
				
			||||||
                                    mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
 | 
					                                    mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
 | 
				
			||||||
                                mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
 | 
					                                mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[7]) #Connect basecolor to pbr node
 | 
				
			||||||
                                mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
 | 
					                                mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[2]) #Connect mixnode to pbr node
 | 
				
			||||||
                                if not scene.TLM_EngineProperties.tlm_target == "vertex":
 | 
					                                if not scene.TLM_EngineProperties.tlm_target == "vertex":
 | 
				
			||||||
                                    mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
 | 
					                                    mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -491,8 +493,9 @@ def applyAOPass():
 | 
				
			|||||||
                                AOMap.image = AOImage
 | 
					                                AOMap.image = AOImage
 | 
				
			||||||
                                AOMap.location = -800, 0
 | 
					                                AOMap.location = -800, 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                AOMult = nodes.new(type="ShaderNodeMixRGB")
 | 
					                                AOMult = nodes.new(type="ShaderNodeMix")
 | 
				
			||||||
                                AOMult.name = "TLM_AOMult"
 | 
					                                AOMult.name = "TLM_AOMult"
 | 
				
			||||||
 | 
					                                AOMult.data_type = 'RGBA'
 | 
				
			||||||
                                AOMult.blend_type = 'MULTIPLY'
 | 
					                                AOMult.blend_type = 'MULTIPLY'
 | 
				
			||||||
                                AOMult.inputs[0].default_value = 1.0
 | 
					                                AOMult.inputs[0].default_value = 1.0
 | 
				
			||||||
                                AOMult.location = -300, 300
 | 
					                                AOMult.location = -300, 300
 | 
				
			||||||
 | 
				
			|||||||
@ -518,7 +518,7 @@ def configure_meshes(self):
 | 
				
			|||||||
                                if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
					                                if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
				
			||||||
                                    print("The material group is not supported!")
 | 
					                                    print("The material group is not supported!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (mainNode.type == "ShaderNodeMixRGB"):
 | 
					                        if (mainNode.type == "ShaderNodeMix"):
 | 
				
			||||||
                            if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
					                            if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
 | 
				
			||||||
                                print("Mix shader found")
 | 
					                                print("Mix shader found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -811,7 +811,7 @@ def set_settings():
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    print(bpy.app.version)
 | 
					    print(bpy.app.version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if bpy.app.version[0] == 3:
 | 
					    if bpy.app.version[0] == 3 or byp.app.version[0] == 4:
 | 
				
			||||||
        if cycles.device == "GPU":
 | 
					        if cycles.device == "GPU":
 | 
				
			||||||
            scene.cycles.tile_size = 256
 | 
					            scene.cycles.tile_size = 256
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,11 @@ class ViewportDraw:
 | 
				
			|||||||
        w = 400
 | 
					        w = 400
 | 
				
			||||||
        h = 200
 | 
					        h = 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if bpy.app.version[0] == 3:
 | 
				
			||||||
            self.shader = gpu.shader.from_builtin('2D_IMAGE')
 | 
					            self.shader = gpu.shader.from_builtin('2D_IMAGE')
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.shader = gpu.shader.from_builtin('IMAGE')
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
        self.batch = batch_for_shader(
 | 
					        self.batch = batch_for_shader(
 | 
				
			||||||
            self.shader, 'TRI_FAN',
 | 
					            self.shader, 'TRI_FAN',
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
@ -34,7 +34,7 @@ class Shader_Node_Types:
 | 
				
			|||||||
    normal = "ShaderNodeNormalMap"
 | 
					    normal = "ShaderNodeNormalMap"
 | 
				
			||||||
    ao = "ShaderNodeAmbientOcclusion"
 | 
					    ao = "ShaderNodeAmbientOcclusion"
 | 
				
			||||||
    uv = "ShaderNodeUVMap"
 | 
					    uv = "ShaderNodeUVMap"
 | 
				
			||||||
    mix = "ShaderNodeMixRGB"
 | 
					    mix = "ShaderNodeMix"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def select_object(self,obj):
 | 
					def select_object(self,obj):
 | 
				
			||||||
    C = bpy.context
 | 
					    C = bpy.context
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,7 @@ def init_categories():
 | 
				
			|||||||
    lnx_nodes.add_category('Navmesh', icon='UV_VERTEXSEL', section="motion")
 | 
					    lnx_nodes.add_category('Navmesh', icon='UV_VERTEXSEL', section="motion")
 | 
				
			||||||
    lnx_nodes.add_category('Transform', icon='TRANSFORM_ORIGINS', section="motion")
 | 
					    lnx_nodes.add_category('Transform', icon='TRANSFORM_ORIGINS', section="motion")
 | 
				
			||||||
    lnx_nodes.add_category('Physics', icon='PHYSICS', section="motion")
 | 
					    lnx_nodes.add_category('Physics', icon='PHYSICS', section="motion")
 | 
				
			||||||
 | 
					    lnx_nodes.add_category('Particle', icon='PARTICLE_DATA', section="motion")
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    lnx_nodes.add_category('Array', icon='MOD_ARRAY', section="values")
 | 
					    lnx_nodes.add_category('Array', icon='MOD_ARRAY', section="values")
 | 
				
			||||||
    lnx_nodes.add_category('Map', icon='SHORTDISPLAY', section="values")
 | 
					    lnx_nodes.add_category('Map', icon='SHORTDISPLAY', section="values")
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
 | 
				
			|||||||
    @input Object: Object of which to choose the material in the `Material Slot` input.
 | 
					    @input Object: Object of which to choose the material in the `Material Slot` input.
 | 
				
			||||||
    @input Material Slot: Index of the material slot of which the diffuse
 | 
					    @input Material Slot: Index of the material slot of which the diffuse
 | 
				
			||||||
        texture is replaced with the camera's render target.
 | 
					        texture is replaced with the camera's render target.
 | 
				
			||||||
 | 
					    @input Node: Node name of the Image Texture Node.
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @output On Start: Activated after the `Start` input has been activated.
 | 
					    @output On Start: Activated after the `Start` input has been activated.
 | 
				
			||||||
    @output On Stop: Activated after the `Stop` input has been activated.
 | 
					    @output On Stop: Activated after the `Stop` input has been activated.
 | 
				
			||||||
@ -18,7 +19,7 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
 | 
				
			|||||||
    bl_idname = 'LNDrawCameraTextureNode'
 | 
					    bl_idname = 'LNDrawCameraTextureNode'
 | 
				
			||||||
    bl_label = 'Draw Camera to Texture'
 | 
					    bl_label = 'Draw Camera to Texture'
 | 
				
			||||||
    lnx_section = 'draw'
 | 
					    lnx_section = 'draw'
 | 
				
			||||||
    lnx_version = 1
 | 
					    lnx_version = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lnx_init(self, context):
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
        self.add_input('LnxNodeSocketAction', 'Start')
 | 
					        self.add_input('LnxNodeSocketAction', 'Start')
 | 
				
			||||||
@ -26,6 +27,13 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
 | 
				
			|||||||
        self.add_input('LnxNodeSocketObject', 'Camera')
 | 
					        self.add_input('LnxNodeSocketObject', 'Camera')
 | 
				
			||||||
        self.add_input('LnxNodeSocketObject', 'Object')
 | 
					        self.add_input('LnxNodeSocketObject', 'Object')
 | 
				
			||||||
        self.add_input('LnxIntSocket', 'Material Slot')
 | 
					        self.add_input('LnxIntSocket', 'Material Slot')
 | 
				
			||||||
 | 
					        self.add_input('LnxStringSocket', 'Node')
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        self.add_output('LnxNodeSocketAction', 'On Start')
 | 
					        self.add_output('LnxNodeSocketAction', 'On Start')
 | 
				
			||||||
        self.add_output('LnxNodeSocketAction', 'On Stop')
 | 
					        self.add_output('LnxNodeSocketAction', 'On Stop')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
				
			||||||
 | 
					        if self.lnx_version not in (0, 1):
 | 
				
			||||||
 | 
					            raise LookupError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return NodeReplacement.Identity(self)
 | 
				
			||||||
							
								
								
									
										44
									
								
								leenkx/blender/lnx/logicnode/draw/LN_draw_sub_image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								leenkx/blender/lnx/logicnode/draw/LN_draw_sub_image.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DrawSubImageNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Draws an image.
 | 
				
			||||||
 | 
					    @input Draw: Activate to draw the image on this frame. The input must
 | 
				
			||||||
 | 
					        be (indirectly) called from an `On Render2D` node.
 | 
				
			||||||
 | 
					    @input Image: The filename of the image.
 | 
				
			||||||
 | 
					    @input Color: The color that the image's pixels are multiplied with.
 | 
				
			||||||
 | 
					    @input Left/Center/Right: Horizontal anchor point of the image.
 | 
				
			||||||
 | 
					        0 = Left, 1 = Center, 2 = Right
 | 
				
			||||||
 | 
					    @input Top/Middle/Bottom: Vertical anchor point of the image.
 | 
				
			||||||
 | 
					        0 = Top, 1 = Middle, 2 = Bottom
 | 
				
			||||||
 | 
					    @input X/Y: Position of the anchor point in pixels.
 | 
				
			||||||
 | 
					    @input Width/Height: Size of the sub image in pixels.
 | 
				
			||||||
 | 
					    @input sX/Y: Position of the sub anchor point in pixels.
 | 
				
			||||||
 | 
					    @input sWidth/Height: Size of the image in pixels.
 | 
				
			||||||
 | 
					    @input Angle: Rotation angle in radians. Image will be rotated cloclwiswe
 | 
				
			||||||
 | 
					        at the anchor point.
 | 
				
			||||||
 | 
					    @output Out: Activated after the image has been drawn.
 | 
				
			||||||
 | 
					    @see [`kha.graphics2.Graphics.drawImage()`](http://kha.tech/api/kha/graphics2/Graphics.html#drawImage).
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    bl_idname = 'LNDrawSubImageNode'
 | 
				
			||||||
 | 
					    bl_label = 'Draw Sub Image'
 | 
				
			||||||
 | 
					    lnx_section = 'draw'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'Draw')
 | 
				
			||||||
 | 
					        self.add_input('LnxStringSocket', 'Image File')
 | 
				
			||||||
 | 
					        self.add_input('LnxColorSocket', 'Color', default_value=[1.0, 1.0, 1.0, 1.0])
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', '0/1/2 = Left/Center/Right', default_value=0)
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', '0/1/2 = Top/Middle/Bottom', default_value=0)
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'X')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Y')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Width')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Height')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'sX')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'sY')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'sWidth')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'sHeight')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Angle')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out') 
 | 
				
			||||||
@ -5,8 +5,6 @@ class WriteFileNode(LnxLogicTreeNode):
 | 
				
			|||||||
    """Writes the given string content to the given file. If the file
 | 
					    """Writes the given string content to the given file. If the file
 | 
				
			||||||
    already exists, the existing content of the file is overwritten.
 | 
					    already exists, the existing content of the file is overwritten.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    > **This node is currently only implemented on Krom**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @input File: the name of the file, relative to `Krom.getFilesLocation()`
 | 
					    @input File: the name of the file, relative to `Krom.getFilesLocation()`
 | 
				
			||||||
    @input Content: the content to write to the file.
 | 
					    @input Content: the content to write to the file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										34
									
								
								leenkx/blender/lnx/logicnode/native/LN_write_image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								leenkx/blender/lnx/logicnode/native/LN_write_image.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class WriteImageNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Writes the given image to the given file. If the image
 | 
				
			||||||
 | 
					    already exists, the existing content of the image is overwritten.
 | 
				
			||||||
 | 
					    Aspect ratio must match display resolution ratio.
 | 
				
			||||||
 | 
					    @input Image File: the name of the image, relative to `Krom.getFilesLocation()`
 | 
				
			||||||
 | 
					    @input Camera: the render target image of the camera to write to the image file.
 | 
				
			||||||
 | 
					    @input Width: width of the image file.
 | 
				
			||||||
 | 
					    @input Height: heigth of the image file.
 | 
				
			||||||
 | 
					    @input sX: sub position of first x pixel of the sub image (0 for start).
 | 
				
			||||||
 | 
					    @input sY: sub position of first y pixel of the sub image (0 for start).
 | 
				
			||||||
 | 
					    @input sWidth: width of the sub image.
 | 
				
			||||||
 | 
					    @input sHeight: height of the sub image.
 | 
				
			||||||
 | 
					    @seeNode Read File
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    bl_idname = 'LNWriteImageNode'
 | 
				
			||||||
 | 
					    bl_label = 'Write Image'
 | 
				
			||||||
 | 
					    lnx_section = 'file'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
 | 
					        self.add_input('LnxStringSocket', 'Image File')
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketObject', 'Camera')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Width')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Height')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'sX')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'sY')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'sWidth')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'sHeight')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
@ -5,8 +5,6 @@ class WriteJsonNode(LnxLogicTreeNode):
 | 
				
			|||||||
    """Writes the given content to the given JSON file. If the file
 | 
					    """Writes the given content to the given JSON file. If the file
 | 
				
			||||||
    already exists, the existing content of the file is overwritten.
 | 
					    already exists, the existing content of the file is overwritten.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    > **This node is currently only implemented on Krom**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @input File: the name of the file, relative to `Krom.getFilesLocation()`,
 | 
					    @input File: the name of the file, relative to `Krom.getFilesLocation()`,
 | 
				
			||||||
        including the file extension.
 | 
					        including the file extension.
 | 
				
			||||||
    @input Dynamic: the content to write to the file. Can be any type that can
 | 
					    @input Dynamic: the content to write to the file. Can be any type that can
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddParticleToObjectNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Sets the speed of the given particle source."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNAddParticleToObjectNode'
 | 
				
			||||||
 | 
					    bl_label = 'Add Particle To Object'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def remove_extra_inputs(self, context):
 | 
				
			||||||
 | 
					        while len(self.inputs) > 1:
 | 
				
			||||||
 | 
					            self.inputs.remove(self.inputs[-1])
 | 
				
			||||||
 | 
					        if self.property0 == 'Scene':
 | 
				
			||||||
 | 
					            self.add_input('LnxStringSocket', 'Scene From Name')
 | 
				
			||||||
 | 
					            self.add_input('LnxStringSocket', 'Object From Name')
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.add_input('LnxNodeSocketObject', 'Object From')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Slot')
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketObject', 'Object To')
 | 
				
			||||||
 | 
					        self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    property0: HaxeEnumProperty(
 | 
				
			||||||
 | 
					    'property0',
 | 
				
			||||||
 | 
					    items = [('Scene Active', 'Scene Active', 'Scene Active'),
 | 
				
			||||||
 | 
					             ('Scene', 'Scene', 'Scene')],
 | 
				
			||||||
 | 
					    name='', default='Scene Active', update=remove_extra_inputs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketObject', 'Object From')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Slot')
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketObject', 'Object To')
 | 
				
			||||||
 | 
					        self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def draw_buttons(self, context, layout):
 | 
				
			||||||
 | 
					        layout.prop(self, 'property0')
 | 
				
			||||||
 | 
					       
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								leenkx/blender/lnx/logicnode/particle/LN_get_particle.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								leenkx/blender/lnx/logicnode/particle/LN_get_particle.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GetParticleNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Returns the Particle Systems of an object."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNGetParticleNode'
 | 
				
			||||||
 | 
					    bl_label = 'Get Particle'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.inputs.new('LnxNodeSocketObject', 'Object')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.outputs.new('LnxNodeSocketArray', 'Names')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxIntSocket', 'Length')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxBoolSocket', 'Render Emitter')
 | 
				
			||||||
@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GetParticleDataNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Returns the data of the given Particle System."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNGetParticleDataNode'
 | 
				
			||||||
 | 
					    bl_label = 'Get Particle Data'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.inputs.new('LnxNodeSocketObject', 'Object')
 | 
				
			||||||
 | 
					        self.inputs.new('LnxIntSocket', 'Slot')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.outputs.new('LnxStringSocket', 'Name')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxFloatSocket', 'Particle Size')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxIntSocket', 'Frame Start')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxIntSocket', 'Frame End')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxIntSocket', 'Lifetime')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxFloatSocket', 'Lifetime Random')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxIntSocket', 'Emit From')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.outputs.new('LnxVectorSocket', 'Velocity')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxFloatSocket', 'Velocity Random')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxVectorSocket', 'Gravity')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxFloatSocket', 'Weight Gravity')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.outputs.new('LnxFloatSocket', 'Speed')
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        self.outputs.new('LnxFloatSocket', 'Time')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxFloatSocket', 'Lap')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxFloatSocket', 'Lap Time')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxIntSocket', 'Count')
 | 
				
			||||||
@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RemoveParticleFromObjectNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Remove Particle From Object."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNRemoveParticleFromObjectNode'
 | 
				
			||||||
 | 
					    bl_label = 'Remove Particle From Object'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def remove_extra_inputs(self, context):
 | 
				
			||||||
 | 
					        while len(self.inputs) > 2:
 | 
				
			||||||
 | 
					                self.inputs.remove(self.inputs[-1])
 | 
				
			||||||
 | 
					        if self.property0 == 'Slot':
 | 
				
			||||||
 | 
					            self.add_input('LnxIntSocket', 'Slot')
 | 
				
			||||||
 | 
					        if self.property0 == 'Name':
 | 
				
			||||||
 | 
					            self.add_input('LnxStringSocket', 'Name')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    property0: HaxeEnumProperty(
 | 
				
			||||||
 | 
					    'property0',
 | 
				
			||||||
 | 
					    items = [('Slot', 'Slot', 'Slot'),
 | 
				
			||||||
 | 
					             ('Name', 'Name', 'Name'),
 | 
				
			||||||
 | 
					             ('All', 'All', 'All')],
 | 
				
			||||||
 | 
					    name='', default='Slot', update=remove_extra_inputs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketObject', 'Object')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Slot')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def draw_buttons(self, context, layout):
 | 
				
			||||||
 | 
					        layout.prop(self, 'property0')
 | 
				
			||||||
@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SetParticleDataNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Sets the parameters of the given particle system."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNSetParticleDataNode'
 | 
				
			||||||
 | 
					    bl_label = 'Set Particle Data'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def remove_extra_inputs(self, context):
 | 
				
			||||||
 | 
					        while len(self.inputs) > 3:
 | 
				
			||||||
 | 
					                self.inputs.remove(self.inputs[-1])
 | 
				
			||||||
 | 
					        if self.property0 == 'Particle Size':
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Particle Size')
 | 
				
			||||||
 | 
					        if self.property0 == 'Frame End':
 | 
				
			||||||
 | 
					            self.add_input('LnxIntSocket', 'Frame End')
 | 
				
			||||||
 | 
					        if self.property0 == 'Frame Start':
 | 
				
			||||||
 | 
					            self.add_input('LnxIntSocket', 'Frame Start')
 | 
				
			||||||
 | 
					        if self.property0 == 'Lifetime': 
 | 
				
			||||||
 | 
					            self.add_input('LnxIntSocket', 'Lifetime')
 | 
				
			||||||
 | 
					        if self.property0 == 'Lifetime Random':
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Lifetime Random')
 | 
				
			||||||
 | 
					        if self.property0 == 'Emit From':
 | 
				
			||||||
 | 
					            self.add_input('LnxIntSocket', 'Emit From')
 | 
				
			||||||
 | 
					        if self.property0 == 'Velocity':
 | 
				
			||||||
 | 
					            self.add_input('LnxVectorSocket', 'Velocity')
 | 
				
			||||||
 | 
					        if self.property0 == 'Velocity Random':
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Velocity Random')
 | 
				
			||||||
 | 
					        if self.property0 == 'Weight Gravity':
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Weight Gravity')
 | 
				
			||||||
 | 
					        if self.property0 == 'Speed':
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Speed')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       
 | 
				
			||||||
 | 
					    property0: HaxeEnumProperty(
 | 
				
			||||||
 | 
					    'property0',
 | 
				
			||||||
 | 
					    items = [('Particle Size', 'Particle Size', 'for the system'),
 | 
				
			||||||
 | 
					             ('Frame Start', 'Frame Start', 'for the system'),
 | 
				
			||||||
 | 
					             ('Frame End', 'Frame End', 'for the system'),
 | 
				
			||||||
 | 
					             ('Lifetime', 'Lifetime', 'for the instance'),
 | 
				
			||||||
 | 
					             ('Lifetime Random', 'Lifetime Random', 'for the system'),
 | 
				
			||||||
 | 
					             ('Emit From', 'Emit From', 'for the system (Vertices:0 Faces:1 Volume: 2)'),
 | 
				
			||||||
 | 
					             ('Velocity', 'Velocity', 'for the instance'),
 | 
				
			||||||
 | 
					             ('Velocity Random', 'Velocity Random', 'for the system'),
 | 
				
			||||||
 | 
					             ('Weight Gravity', 'Weight Gravity', 'for the instance'),
 | 
				
			||||||
 | 
					             ('Speed', 'Speed', 'for the instance')],
 | 
				
			||||||
 | 
					    name='', default='Speed', update=remove_extra_inputs)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketObject', 'Object')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Slot')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def draw_buttons(self, context, layout):
 | 
				
			||||||
 | 
					        layout.prop(self, 'property0')
 | 
				
			||||||
@ -4,11 +4,19 @@ class SetParticleSpeedNode(LnxLogicTreeNode):
 | 
				
			|||||||
    """Sets the speed of the given particle source."""
 | 
					    """Sets the speed of the given particle source."""
 | 
				
			||||||
    bl_idname = 'LNSetParticleSpeedNode'
 | 
					    bl_idname = 'LNSetParticleSpeedNode'
 | 
				
			||||||
    bl_label = 'Set Particle Speed'
 | 
					    bl_label = 'Set Particle Speed'
 | 
				
			||||||
    lnx_version = 1
 | 
					    lnx_version = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lnx_init(self, context):
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
        self.add_input('LnxNodeSocketObject', 'Object')
 | 
					        self.add_input('LnxNodeSocketObject', 'Object')
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Slot')
 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
 | 
					        self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
				
			||||||
 | 
					        if self.lnx_version not in (0, 1):
 | 
				
			||||||
 | 
					            raise LookupError()
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        return NodeReplacement.Identity(self)
 | 
				
			||||||
							
								
								
									
										3
									
								
								leenkx/blender/lnx/logicnode/particle/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								leenkx/blender/lnx/logicnode/particle/__init__.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import add_node_section
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_node_section(name='default', category='Particle')
 | 
				
			||||||
@ -234,7 +234,7 @@ def build():
 | 
				
			|||||||
                wrd.compo_defs += '_CGrain'
 | 
					                wrd.compo_defs += '_CGrain'
 | 
				
			||||||
            if rpdat.lnx_sharpen:
 | 
					            if rpdat.lnx_sharpen:
 | 
				
			||||||
                wrd.compo_defs += '_CSharpen'
 | 
					                wrd.compo_defs += '_CSharpen'
 | 
				
			||||||
            if bpy.data.scenes[0].view_settings.exposure != 0.0:
 | 
					            if bpy.utils.get_active_scene().view_settings.exposure != 0.0:
 | 
				
			||||||
                wrd.compo_defs += '_CExposure'
 | 
					                wrd.compo_defs += '_CExposure'
 | 
				
			||||||
            if rpdat.lnx_fog:
 | 
					            if rpdat.lnx_fog:
 | 
				
			||||||
                wrd.compo_defs += '_CFog'
 | 
					                wrd.compo_defs += '_CFog'
 | 
				
			||||||
 | 
				
			|||||||
@ -298,6 +298,125 @@ float tex_brick_f(vec3 p) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#https://github.com/blender/blender/blob/main/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl
 | 
				
			||||||
 | 
					str_tex_brick_blender = """
 | 
				
			||||||
 | 
					float integer_noise(int n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  /* Integer bit-shifts for these calculations can cause precision problems on macOS.
 | 
				
			||||||
 | 
					   * Using uint resolves these issues. */
 | 
				
			||||||
 | 
					  uint nn;
 | 
				
			||||||
 | 
					  nn = (uint(n) + 1013u) & 0x7fffffffu;
 | 
				
			||||||
 | 
					  nn = (nn >> 13u) ^ nn;
 | 
				
			||||||
 | 
					  nn = (uint(nn * (nn * nn * 60493u + 19990303u)) + 1376312589u) & 0x7fffffffu;
 | 
				
			||||||
 | 
					  return 0.5f * (float(nn) / 1073741824.0f);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					vec2 calc_brick_texture(vec3 p,
 | 
				
			||||||
 | 
					                          float mortar_size,
 | 
				
			||||||
 | 
					                          float mortar_smooth,
 | 
				
			||||||
 | 
					                          float bias,
 | 
				
			||||||
 | 
					                          float brick_width,
 | 
				
			||||||
 | 
					                          float row_height,
 | 
				
			||||||
 | 
					                          float offset_amount,
 | 
				
			||||||
 | 
					                          int offset_frequency,
 | 
				
			||||||
 | 
					                          float squash_amount,
 | 
				
			||||||
 | 
					                          int squash_frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int bricknum, rownum;
 | 
				
			||||||
 | 
					  float offset = 0.0f;
 | 
				
			||||||
 | 
					  float x, y;
 | 
				
			||||||
 | 
					  rownum = int(floor(p.y / row_height));
 | 
				
			||||||
 | 
					  if (offset_frequency != 0 && squash_frequency != 0) {
 | 
				
			||||||
 | 
					    brick_width *= (rownum % squash_frequency != 0) ? 1.0f : squash_amount;           /* squash */
 | 
				
			||||||
 | 
					    offset = (rownum % offset_frequency != 0) ? 0.0f : (brick_width * offset_amount); /* offset */
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  bricknum = int(floor((p.x + offset) / brick_width));
 | 
				
			||||||
 | 
					  x = (p.x + offset) - brick_width * bricknum;
 | 
				
			||||||
 | 
					  y = p.y - row_height * rownum;
 | 
				
			||||||
 | 
					  float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f);
 | 
				
			||||||
 | 
					  float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
 | 
				
			||||||
 | 
					  if (min_dist >= mortar_size) {
 | 
				
			||||||
 | 
					    return vec2(tint, 0.0f);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (mortar_smooth == 0.0f) {
 | 
				
			||||||
 | 
					    return vec2(tint, 1.0f);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    min_dist = 1.0f - min_dist / mortar_size;
 | 
				
			||||||
 | 
					    return vec2(tint, smoothstep(0.0f, mortar_smooth, min_dist));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					vec3 tex_brick_blender(vec3 co,
 | 
				
			||||||
 | 
					                    vec3 color1,
 | 
				
			||||||
 | 
					                    vec3 color2,
 | 
				
			||||||
 | 
					                    vec3 mortar,
 | 
				
			||||||
 | 
					                    float scale,
 | 
				
			||||||
 | 
					                    float mortar_size,
 | 
				
			||||||
 | 
					                    float mortar_smooth,
 | 
				
			||||||
 | 
					                    float bias,
 | 
				
			||||||
 | 
					                    float brick_width,
 | 
				
			||||||
 | 
					                    float row_height,
 | 
				
			||||||
 | 
					                    float offset_amount,
 | 
				
			||||||
 | 
					                    float offset_frequency,
 | 
				
			||||||
 | 
					                    float squash_amount,
 | 
				
			||||||
 | 
					                    float squash_frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  vec2 f2 = calc_brick_texture(co * scale,
 | 
				
			||||||
 | 
					                                 mortar_size,
 | 
				
			||||||
 | 
					                                 mortar_smooth,
 | 
				
			||||||
 | 
					                                 bias,
 | 
				
			||||||
 | 
					                                 brick_width,
 | 
				
			||||||
 | 
					                                 row_height,
 | 
				
			||||||
 | 
					                                 offset_amount,
 | 
				
			||||||
 | 
					                                 int(offset_frequency),
 | 
				
			||||||
 | 
					                                 squash_amount,
 | 
				
			||||||
 | 
					                                 int(squash_frequency));
 | 
				
			||||||
 | 
					  float tint = f2.x;
 | 
				
			||||||
 | 
					  float f = f2.y;
 | 
				
			||||||
 | 
					  if (f != 1.0f) {
 | 
				
			||||||
 | 
					    float facm = 1.0f - tint;
 | 
				
			||||||
 | 
					    color1 = facm * color1 + tint * color2;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					    return mix(color1, mortar, f);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					float tex_brick_blender_f(vec3 co,
 | 
				
			||||||
 | 
					                    vec3 color1,
 | 
				
			||||||
 | 
					                    vec3 color2,
 | 
				
			||||||
 | 
					                    vec3 mortar,
 | 
				
			||||||
 | 
					                    float scale,
 | 
				
			||||||
 | 
					                    float mortar_size,
 | 
				
			||||||
 | 
					                    float mortar_smooth,
 | 
				
			||||||
 | 
					                    float bias,
 | 
				
			||||||
 | 
					                    float brick_width,
 | 
				
			||||||
 | 
					                    float row_height,
 | 
				
			||||||
 | 
					                    float offset_amount,
 | 
				
			||||||
 | 
					                    float offset_frequency,
 | 
				
			||||||
 | 
					                    float squash_amount,
 | 
				
			||||||
 | 
					                    float squash_frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  vec2 f2 = calc_brick_texture(co * scale,
 | 
				
			||||||
 | 
					                                 mortar_size,
 | 
				
			||||||
 | 
					                                 mortar_smooth,
 | 
				
			||||||
 | 
					                                 bias,
 | 
				
			||||||
 | 
					                                 brick_width,
 | 
				
			||||||
 | 
					                                 row_height,
 | 
				
			||||||
 | 
					                                 offset_amount,
 | 
				
			||||||
 | 
					                                 int(offset_frequency),
 | 
				
			||||||
 | 
					                                 squash_amount,
 | 
				
			||||||
 | 
					                                 int(squash_frequency));
 | 
				
			||||||
 | 
					  float tint = f2.x;
 | 
				
			||||||
 | 
					  float f = f2.y;
 | 
				
			||||||
 | 
					  if (f != 1.0f) {
 | 
				
			||||||
 | 
					    float facm = 1.0f - tint;
 | 
				
			||||||
 | 
					    color1 = facm * color1 + tint * color2;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					    return f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
str_tex_wave = """
 | 
					str_tex_wave = """
 | 
				
			||||||
float tex_wave_f(const vec3 p, const int type, const int profile, const float dist, const float detail, const float detail_scale) {
 | 
					float tex_wave_f(const vec3 p, const int type, const int profile, const float dist, const float detail, const float detail_scale) {
 | 
				
			||||||
    float n;
 | 
					    float n;
 | 
				
			||||||
 | 
				
			|||||||
@ -29,24 +29,35 @@ else:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def parse_tex_brick(node: bpy.types.ShaderNodeTexBrick, out_socket: bpy.types.NodeSocket, state: ParserState) -> Union[floatstr, vec3str]:
 | 
					def parse_tex_brick(node: bpy.types.ShaderNodeTexBrick, out_socket: bpy.types.NodeSocket, state: ParserState) -> Union[floatstr, vec3str]:
 | 
				
			||||||
    state.curshader.add_function(c_functions.str_tex_brick)
 | 
					    state.curshader.add_function(c_functions.str_tex_brick_blender)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if node.inputs[0].is_linked:
 | 
					    if node.inputs[0].is_linked:
 | 
				
			||||||
        co = c.parse_vector_input(node.inputs[0])
 | 
					        co = c.parse_vector_input(node.inputs[0])
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        co = 'bposition'
 | 
					        co = 'bposition'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Color
 | 
					    offset_amount = node.offset
 | 
				
			||||||
    if out_socket == node.outputs[0]:
 | 
					    offset_frequency = node.offset_frequency
 | 
				
			||||||
 | 
					    squash_amount = node.squash
 | 
				
			||||||
 | 
					    squash_frequency = node.squash_frequency        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    col1 = c.parse_vector_input(node.inputs[1])
 | 
					    col1 = c.parse_vector_input(node.inputs[1])
 | 
				
			||||||
    col2 = c.parse_vector_input(node.inputs[2])
 | 
					    col2 = c.parse_vector_input(node.inputs[2])
 | 
				
			||||||
    col3 = c.parse_vector_input(node.inputs[3])
 | 
					    col3 = c.parse_vector_input(node.inputs[3])
 | 
				
			||||||
    scale = c.parse_value_input(node.inputs[4])
 | 
					    scale = c.parse_value_input(node.inputs[4])
 | 
				
			||||||
        res = f'tex_brick({co} * {scale}, {col1}, {col2}, {col3})'
 | 
					    mortar_size = c.parse_value_input(node.inputs[5])
 | 
				
			||||||
 | 
					    mortar_smooth = c.parse_value_input(node.inputs[6])
 | 
				
			||||||
 | 
					    bias = c.parse_value_input(node.inputs[7])
 | 
				
			||||||
 | 
					    brick_width = c.parse_value_input(node.inputs[8])
 | 
				
			||||||
 | 
					    row_height = c.parse_value_input(node.inputs[9])
 | 
				
			||||||
 | 
					    #res = f'tex_brick({co} * {scale}, {col1}, {col2}, {col3})'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Color
 | 
				
			||||||
 | 
					    if out_socket == node.outputs[0]:
 | 
				
			||||||
 | 
					        res = f'tex_brick_blender({co}, {col1}, {col2}, {col3}, {scale}, {mortar_size}, {mortar_smooth}, {bias}, {brick_width}, {row_height}, {offset_amount}, {offset_frequency}, {squash_amount}, {squash_frequency})'
 | 
				
			||||||
    # Fac
 | 
					    # Fac
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        scale = c.parse_value_input(node.inputs[4])
 | 
					        res = f'tex_brick_blender_f({co}, {col1}, {col2}, {col3}, {scale}, {mortar_size}, {mortar_smooth}, {bias}, {brick_width}, {row_height}, {offset_amount}, {offset_frequency}, {squash_amount}, {squash_frequency})'
 | 
				
			||||||
        res = 'tex_brick_f({0} * {1})'.format(co, scale)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return res
 | 
					    return res
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,7 @@ class LNX_MT_NodeAddOverride(bpy.types.Menu):
 | 
				
			|||||||
                layout.separator()
 | 
					                layout.separator()
 | 
				
			||||||
                layout.menu(f'LNX_MT_{INTERNAL_GROUPS_MENU_ID}_menu', text=internal_groups_menu_class.bl_label, icon='OUTLINER_OB_GROUP_INSTANCE')
 | 
					                layout.menu(f'LNX_MT_{INTERNAL_GROUPS_MENU_ID}_menu', text=internal_groups_menu_class.bl_label, icon='OUTLINER_OB_GROUP_INSTANCE')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elif context.space_data.tree_type == 'ShaderNodeTree':
 | 
					        elif context.space_data.tree_type == 'ShaderNodeTree' and bpy.app.version > (4, 0, 0):
 | 
				
			||||||
            # TO DO - Recursively gather nodes and draw them to menu
 | 
					            # TO DO - Recursively gather nodes and draw them to menu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            LNX_MT_NodeAddOverride.overridden_draw(self, context)
 | 
					            LNX_MT_NodeAddOverride.overridden_draw(self, context)
 | 
				
			||||||
 | 
				
			|||||||
@ -769,9 +769,9 @@ const vec3 compoLetterboxColor = vec3(""" + str(round(rpdat.lnx_letterbox_color[
 | 
				
			|||||||
"""const float compoSharpenStrength = """ + str(round(rpdat.lnx_sharpen_strength * 100) / 100) + """;
 | 
					"""const float compoSharpenStrength = """ + str(round(rpdat.lnx_sharpen_strength * 100) / 100) + """;
 | 
				
			||||||
""")
 | 
					""")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if bpy.data.scenes[0].view_settings.exposure != 0.0:
 | 
					        if bpy.utils.get_active_scene().view_settings.exposure != 0.0:
 | 
				
			||||||
            f.write(
 | 
					            f.write(
 | 
				
			||||||
"""const float compoExposureStrength = """ + str(round(bpy.data.scenes[0].view_settings.exposure * 100) / 100) + """;
 | 
					"""const float compoExposureStrength = """ + str(round(bpy.utils.get_active_scene().view_settings.exposure * 100) / 100) + """;
 | 
				
			||||||
""")
 | 
					""")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if rpdat.lnx_fog:
 | 
					        if rpdat.lnx_fog:
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user