Skip to content

Commit

Permalink
Merge pull request #3108 from t3du/ProbabilisticOutputNode
Browse files Browse the repository at this point in the history
Probabilistic output node
  • Loading branch information
luboslenco authored Dec 24, 2024
2 parents 0fe472d + 412b48d commit 05ece1e
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
40 changes: 40 additions & 0 deletions armory/Sources/armory/logicnode/ProbabilisticOutputNode.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package armory.logicnode;

class ProbabilisticOutputNode extends LogicNode {

public function new(tree: LogicTree) {
super(tree);
}

override function run(from: Int) {

var probs: Array<Float> = [];
var probs_acum: Array<Float> = [];
var sum: Float = 0;

for (p in 1...inputs.length){
probs.push(inputs[p].get());
sum += probs[p-1];
}

if (sum > 1){
trace(sum);
for (p in 0...probs.length)
probs[p] /= sum;
}

sum = 0;
for (p in 0...probs.length){
sum += probs[p];
probs_acum.push(sum);
}

var rand: Float = Math.random();

for (p in 0...probs.length){
if (p == 0 && rand <= probs_acum[p]){ runOutput(p); break; }
else if (0 < p && p < probs.length-1 && probs_acum[p-1] < rand && rand <= probs_acum[p]){ runOutput(p); break; }
else if (p == probs.length-1 && probs_acum[p-1] < rand){ runOutput(p); break; }
}
}
}
56 changes: 56 additions & 0 deletions armory/blender/arm/logicnode/random/LN_probabilistic_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from arm.logicnode.arm_nodes import *


class ProbabilisticOutputNode(ArmLogicTreeNode):
"""This system activates an output based on probabilistic values,
ensuring that the total sum of the probabilities equals 1.
If the probabilities do not sum to 1, they will be adjusted
accordingly to guarantee a total sum of 1. Only one output will be
triggered at a time.
@input prob: probability of output.
@output output: output.
"""

bl_idname = 'LNProbabilisticOutputNode'
bl_label = 'Probabilistic Output'
arm_section = 'logic'
arm_version = 1

num_choices: IntProperty(default=0, min=0)

def __init__(self):
array_nodes[str(id(self))] = self

def arm_init(self, context):

self.add_input('ArmNodeSocketAction', 'In')

def draw_buttons(self, context, layout):
row = layout.row(align=True)

op = row.operator('arm.node_call_func', text='New', icon='PLUS', emboss=True)
op.node_index = str(id(self))
op.callback_name = 'add_func'
op2 = row.operator('arm.node_call_func', text='', icon='X', emboss=True)
op2.node_index = str(id(self))
op2.callback_name = 'remove_func'

def add_func(self):
self.add_input('ArmFloatSocket', f'Prob {self.num_choices}')
self.add_output('ArmNodeSocketAction', f'Output {self.num_choices}')
self.num_choices += 1

def remove_func(self):
if len(self.inputs) > 1:
self.inputs.remove(self.inputs[-1])
self.outputs.remove(self.outputs[-1])
self.num_choices -= 1

def draw_label(self) -> str:
if self.num_choices == 0:
return self.bl_label

return f'{self.bl_label}: [{self.num_choices}]'

0 comments on commit 05ece1e

Please sign in to comment.