Make only some Dynatree nodes droppable - droppable

I have a tree with regular nodes and also some nodes that have Class1 added to them:
addClass: "custom1"
How can I prevent dropping on custom1 nodes and allow dropping on all other (regular) nodes?

Add a line to the onDrop handler to check the data.addClass of the target node:
onDrop: function(node, sourceNode, hitMode, ui, draggable) {
if( node.data.addClass == 'custom1'){
return;
}
// move the source
}

Related

How to use in each statement with mixed version dml devices?

Got a device with some common code in DML 1.4 where I want to verify a parameter is properly set on all fields of all registers by using and in each statement:
dml 1.4;
//import "each-bank.dml";
template stop_template {
param stop default true;
}
template dont_stop is stop_template{
param stop = false;
}
in each bank {
in each register {
in each field {
is stop_template;
#if (this.stop)
{
error "Stop here";
}
}
}
}
For a device in dml 1.2 my error statements triggers on d.o even if I add the template or parameter myself:
dml 1.2;
device each_device;
import "each-import.dml"
bank a {
register x size 4 #0x0 {
field alpha #[2:0] {
is dont_stop;
}
}
}
bank d {
register o size 4 #0x0 is stop_template;
}
DML-DEP each-device.dmldep
DEP each-device-dml.d
DMLC each-device-dml.c
Using the Simics 5 API for test-device module
/modules/test-device/each-device.dml:15:5: In d.o
/modules/test-device/each-import.dml:18:17: error: Stop here
...
gmake: *** [test-device] Error 2
Running the same code with an 1.4 device works as intended. Does the in each statement does not work with mixed devices?
Your issue is that in dml 1.2 registers with no declared fields get one whole-register-covering field implicitly defined by the compilator. This is then picked up by your each-statement, correctly.
To work around this, you need your template to check if it is actually being applied to an explicit field (part of the unfortunate pain that comes with writing common-code for both 1.2 and 1.4).
To do this: use the 1.2 parameter 'explicit' which is set by the compiler, which is 'true' for declared fields only. This parameter is however not present in 1.4, so you need to additionally guard this check with a check on the 'dml_1_2' parameter.
Something along the lines of:
in each bank {
in each register {
in each field {
// We cannot put this inside the hashif, despite wanting to,
// because DML does not (yet) allow conditional templating on
// parameters
is stop_template;
// This _does_ mean we can check this.stop first, saving us
// a little bit of code
#if (this.stop) {
// It is generally considered good practice to keep
// dml_1_2 checks in their own #if branch, so that they
// can be removed wholesale once 1.2 is no longer supported
#if (dml_1_2) {
#if (explicit) {
error "Stop here";
}
} #else {
error "Stop here";
}
}
}
}
}
In your case, the problematic code is a consistency check that's not strictly necessary for the device to function, so one option is to just skip this check for DML 1.2, assuming that most remaining DML 1.2 devices are legacy things where not much development is happening. So you can just put the problematic definitions inside #if (!dml_1_2) { } and it will compile again. Note that the compiler has a special case for the dml_1_2 parameter, which allows a top-level #if to contain any kind of top-level statement, including template definitions and typedefs.

Should the variable value be checked before assigning?

I know this might sound like a silly question but I'm curious should I check my variable value before assigning?
like for example if I'm flipping my skin (Node2D composed of sprite & raycast) based on direction (Vector2) :
func _process(delta):
...
if(direction.x>0):
skin.scale.x=1
elif(direction.x<0):
skin.scale.x=-1
#OR
if(direction.x>0):
if(skin.scale.x!=1):
skin.scale.x=1
elif(direction.x<0):
if(skin.scale.x!=-1):
skin.scale.x=-1
would the skin scale be altered every _process hence consuming more CPU usage
OR
if the value is same will it be ignored?
First of all, given that this is GDScript, so the number of lines will be a performance factor.
We will look at the C++ side…
But before that… Be aware that GDScript does some trickery with properties.
When you say skin.scale Godot will call get_scale on the skin object, which returns a Vector2. And Vector2 is a value type. That Vector2 is not the scale that the object has, but a copy, an snapshot of the value. So, in virtually any other language skin.scale.x=1 is modifying the Vector2 and would have no effect on the scale of the object. Meaning that you should do this:
skin.scale = Vector2(skin.scale.x + 1, skin.scale.y)
Or this:
var skin_scale = skin.scale
skin_scale.x += 1
skin.scale = skin_scale
Which I bet people using C# would find familiar.
But you don't need to do that in GDScript. Godot will call set_scale, which is what most people expect. It is a feature!
So, you set scale, and Godot will call set_scale:
void Node2D::set_scale(const Size2 &p_scale) {
if (_xform_dirty) {
((Node2D *)this)->_update_xform_values();
}
_scale = p_scale;
// Avoid having 0 scale values, can lead to errors in physics and rendering.
if (Math::is_zero_approx(_scale.x)) {
_scale.x = CMP_EPSILON;
}
if (Math::is_zero_approx(_scale.y)) {
_scale.y = CMP_EPSILON;
}
_update_transform();
_change_notify("scale");
}
The method _change_notify only does something in the editor. It is the Godot 3.x instrumentation for undo/redo et.al.
And set_scale will call _update_transform:
void Node2D::_update_transform() {
_mat.set_rotation_and_scale(angle, _scale);
_mat.elements[2] = pos;
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), _mat);
if (!is_inside_tree()) {
return;
}
_notify_transform();
}
Which, as you can see, will update the Transform2D of the Node2D (_mat). Then it is off to the VisualServer.
And then to _notify_transform. Which is what propagates the change in the scene tree. It is also what calls notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED) if you have enabled it with set_notify_transform. It looks like this (this is from "canvas_item.h"):
_FORCE_INLINE_ void _notify_transform() {
if (!is_inside_tree()) {
return;
}
_notify_transform(this);
if (!block_transform_notify && notify_local_transform) {
notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
}
}
And you can see it delegates to another _notify_transform that looks like this (this is from "canvas_item.cpp"):
void CanvasItem::_notify_transform(CanvasItem *p_node) {
/* This check exists to avoid re-propagating the transform
* notification down the tree on dirty nodes. It provides
* optimization by avoiding redundancy (nodes are dirty, will get the
* notification anyway).
*/
if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid) {
return; //nothing to do
}
p_node->global_invalid = true;
if (p_node->notify_transform && !p_node->xform_change.in_list()) {
if (!p_node->block_transform_notify) {
if (p_node->is_inside_tree()) {
get_tree()->xform_change_list.add(&p_node->xform_change);
}
}
}
for (CanvasItem *ci : p_node->children_items) {
if (ci->top_level) {
continue;
}
_notify_transform(ci);
}
}
So, no. There is no check to ignore the change if the value is the same.
However, it is worth noting that Godot invalidates the global transform instead of computing it right away (global_invalid). This is does not make multiple updates to the transform in the same frame free, but it makes them cheaper than otherwise.
I also remind you that looking at the source code is no replacement for using a profiler.
Should you check? Perhaps… If there are many children that need to be updated the extra lines are likely cheap enough. If in doubt: measure with a profiler.

How to develop an Import/Export Functionality for my node application

I have a configuration application in Nodejs. It has a Component with name and uuid. A Component can have many Schemas. A Schema has a uuid, name, componentId, json. A Schema can have many Configurations. A Configuration has name, schemaId, json and uuid. A Schema can contain reference of many other Schemas in it. Now I want to create a functionality of exporting all the data from one instance of the application and import it in another. What should be the simplest way to do it? a few questions are
How to tell application what to export. for now i think there should be separate arrays for components, schemas and configurations. Like
{
components: ['id1', 'id2'],
schemas: ['s1', 's2'],
configuration: ['c1', 'c2'],
}
this data should be sent to application to return a file with all information that will later be used for importing in another instance
The real question is how should my export file look like keeping in mind that dependencies are also involved and dependencies can also overlap. for example a schema can have many other schemas referenced in its json field. eg schema1 has schema2 and schema4 as its dependencies. so there is another schema schema5 that also require schema2. so while importing we have to make sure that schema2 should be saved first before saving schema1 and schema5. how to represent such file that requires order as well as overlapped dependencies, making sure that schema2 is not saved twice while importing. json of schema1 is shown below as an example
{
"$schema": "http://json-schema.org/draft-04/schema#",
"p1": {
"$ref": "link-to-schema2"
},
"p2": {
"$ref": "link-to-schema4"
},
}
What should be the step wise sudo algorithm i should follow while importing.
This is a perfect occasion for a topological sort.
Taking away components, schemas and configurations terminology, what you have is objects (of various kinds) which depend on other objects existing first. A topological sort will create an order that has only forward dependencies (assuming you don't have circular ones, in which case it is impossible).
But the complication is that you have dependency information in a mix of directions. A component has to be created before its schema. A schema has to be created after the schemas that it depends on. It is not impossible that those schemas may belong to other components that have to be created as well.
The first step is to write a function that takes an object and returns a set of dependency relationships discoverable from the object itself. So we want dependencyRelations(object1 to give something like [[object1, object2], [object3, object1], [object1, object4]]. Where object1 depends on object2 existing. (Note, object1 will be in each pair but can be first or second.)
If every object has a method named uniqueName that uniquely identifies it then we can write a method that works something like this (apologies, all code was typed here and not tested, there are probably syntax errors but the idea is right):
function dependencyInfo (startingObject) {
const nameToObject = {};
const dependencyOf = {};
const todo = [startingObject];
const visited = {};
while (0 < todo.length) {
let obj = todo.pop();
let objName = obj.uniqueName();
if (! visited[ objName ]) {
visited[ objName ] = true;
nameToObject[objName] = obj;
dependencyRelations(obj).forEach((pair) => {
const [from, to] = pair;
// It is OK to put things in todo that are visited, we just don't process again.
todo.push(from);
todo.push(to);
if (! dependencyOf[from.uniqueName()]) {
dependencyOf[from.uniqueName()] = {}
}
dependencyOf[from.uniqueName()] = to.uniqueName();
});
}
}
return [nameToObject, dependencyOf];
}
This function will construct the dependency graph. But we still need to do a topological sort to get dependencies first.
function objectsInOrder (nameToObject, dependencyOf) {
const answer = [];
visited = {};
// Trick for a recursive function local to my environment.
let addObject = undefined;
addObject = function (objName) {
if (! visited[objName]) {
visited[objName] = true; // Only process once.
// Add dependencies
Object.keys(dependencyOf[objName]).forEach(addObject);
answer.push(nameToObject[objName]);
}
};
Object.keys(dependencyOf).forEach(addObject);
return answer;
}
And now we have an array of objects such that each depends on the previous ones only. Send that, and at the other end you just inflate each object in turn.

When joining vertices, am I forced to use MEMORY_ONLY caching?

Looking at the source of outerJoinVertices
I wonder if this is a bug or a feature
override def outerJoinVertices[U: ClassTag, VD2: ClassTag]
(other: RDD[(VertexId, U)])
(updateF: (VertexId, VD, Option[U]) => VD2)
(implicit eq: VD =:= VD2 = null): Graph[VD2, ED] = {
// The implicit parameter eq will be populated by the compiler if VD and VD2 are equal, and left
// null if not
if (eq != null) {
vertices.cache() // <===== what if I wanted it serialized?
// updateF preserves type, so we can use incremental replication
val newVerts = vertices.leftJoin(other)(updateF).cache()
val changedVerts = vertices.asInstanceOf[VertexRDD[VD2]].diff(newVerts)
val newReplicatedVertexView = replicatedVertexView.asInstanceOf[ReplicatedVertexView[VD2, ED]]
.updateVertices(changedVerts)
new GraphImpl(newVerts, newReplicatedVertexView)
} else {
// updateF does not preserve type, so we must re-replicate all vertices
val newVerts = vertices.leftJoin(other)(updateF)
GraphImpl(newVerts, replicatedVertexView.edges)
}
}
Questions
If my graph / joined vertices are already cached via another StorageLevel (e.g. MEMORY_ONLY_SER) - is this what causes the org.apache.spark.graphx.impl.ShippableVertexPartitionOps ... WARN ShippableVertexPartitionOps: Joining two VertexPartitions with different indexes is slow.?
If this is the case, then is this a bug in Spark (this is from 1.3.1)? couldn't find the JIRA issue on this if it is (but I didn't look too hard...)
Why is it not as trivial to fix as to provide this method a new StorageLevel?
What are the workarounds for this? (one that I can think of, is to do create a new Graph with vertices.join(otherVertices) and originalGraph.edges or something... but it feels wrong...
Well, I think it's actually not a bug.
Looking at the code for VertexRDD it overrides the cache method, and uses the original StorageLevel used to create this vertex.
override def cache(): this.type = {
partitionsRDD.persist(targetStorageLevel)
this
}

How to get the path between 2 nodes using Breadth-First Search?

I am trying to find a path between two nodes in a graph, where the edges are unweighted.
I am using a Breadth First Search, which stops when it finds the target, in order to find the existence of a path, but I am not sure how to get the path itself.
I tried looking at the list of visited nodes, but this did not seem to help.
I saw someone answer this question using prolog, but I am a C++ programmer.
I also looked at Dijkstras algorithm, but this seems like over kill, since a simple Breadth-first Search has got me almost the whole way.
How to get the path between 2 nodes using Breadth-First Search?
In your node struct, you add a variable called parentNode which is the parent of that node in the path. In the end, you can retrieve the path by traversing from the goal node backward.
I found this simple algorithm which stores the path to the node along with the node in the queue here: https://stackoverflow.com/a/50575971/5883177
So when we pop a node from the queue, we also get the path to that node readily.
The code in the link is in python which uses tuples to store the pair. Here is a C++ implementation of the same which uses std::pair.
bool findPath(Node *n1, Node *n2, vector<Node*> &path)
{
// We use queue to perform a BFS traversal and in addition to storing the
// node we'll also store the path so far to the node.
queue<pair<Node*,vector<Node*>>> q;
// Visit the first node and add it to the queue.
n1->visited=1;
// Form the path, create a pair and add it the queue.
vector<Node*> p;
p.push_back(n1);
q.push(make_pair(n1,p));
while(!q.empty())
{
pair<Node*,vector<Node*>> curPair = q.front();
q.pop();
// visit all the unvisited nodes and check if there is n2 in it.
for(Node *u : curPair.first->adjNodes ){
if(u->visited == 0){
if(u->value == n2->value){
// found our destination. Return true
// form the path by appending this node to the path till now
curPair.second.push_back(u);
// update the passed 'path' vector with the path so far.
path = curPair.second; // all nodes will be copied into path
return true;
}
// Not our node, visit the node if unvisited
if(u->visited == 0){
u->visited = 1;
// Create a new path with this node added.
// Path so far can be obtained from the pair in queue
vector<Node*> newPath(curPair.second);
newPath.push_back(u);
// Add the node and the path to it into the queue.
q.push(make_pair(u, newPath));
}
}
}
}
return false;
}
class Node{
public:
Node(int val)
{
value = val;
visited=0;
}
int value;
vector<Node*> adjNodes;
int visited;
};

Resources