GOJS second diagrams's zoom issue - diagram

I have two GOJS diagrams on a same page. one is primary diagram. It gets data on page load and displays the nodes. and it also has a search to find path between nodes.
Search takes source node and destination node. then on search action, the second diagram only displays the nodes involved in search and their links.
I am using mouse wheel for zoom in and zoom out.
mainDiagram.addDiagramListener("InitialLayoutCompleted", function (e) {
e.diagram.toolManager.mouseWheelBehavior = go.ToolManager.WheelZoom;
});
primary diagram has no issue. but the second diagram's zoom does not work. Following is the code for my second diagram.
var myPathDiagram = _go(go.Diagram, "policyPathDiv",
{
initialContentAlignment: go.Spot.Center,
layout: _go(go.LayeredDigraphLayout,
{direction: 0}),
autoScale: go.Diagram.UniformToFill,
maxSelectionCount: 1,
"undoManager.isEnabled": false,
hasHorizontalScrollbar: false,
hasVerticalScrollbar: false,
});
then tools manager setting
myPathDiagram.addDiagramListener("InitialLayoutCompleted", function (e) {
e.diagram.toolManager.mouseWheelBehavior = go.ToolManager.WheelZoom;
});
Second diagram gets the data on search action with following code.
myPathDiagram.model = new go.GraphLinksModel(nodes, links);
Everything is right except zoom on second diagram. keyboard shortcut ctrl + and ctrl - also doesn't work for second diagram.
I tried many things, but so far i am not able to make the zoom work on second diagram. any suggestion please...

Don't set Diagram.autoScale if you want the user to scale (a.k.a. zoom) the diagram.

Related

How to apply shaders and generate images only once?

I'm trying to apply a pixelation shader to my textures and I need it to be applied only once, after that I can reuse my shader generated images as textures over and over without having to calculate every single time.
so how do I take a few images -> apply a shader and render them only once every time the game loads -> and use them as my textures?
so far I've managed to find the shader to apply:
shader_type canvas_item;
uniform int amount = 40;
void fragment()
{
vec2 grid_uv = round(UV * float(amount)) / float(amount);
vec4 text = texture(TEXTURE, grid_uv);
COLOR = text;
}
but I have no idea how to render out the images using it
Shaders reside in the GPU, and their output goes to the screen. To save the image, the CPU would have to see the GPU output, and that does not happen… Usually. And since it does not go through the CPU, the performance is good. Usually. Well, at least it is better than if the CPU was doing it all the time.
Also, are you sure you don't want to get a pixel art look by other means? Such as removing filter from the texture, changing the stretch mode and working on a small resolution, and perhaps enable pixel snap? No? Watch How to make a silky smooth camera for pixelart games in Godot. Still No? Ok...
Anyway, for what you want, you are going to need a Viewport.
Viewport setup
What you will need is to create a Viewport. Don't forget to set its size. Also may want to set render_target_v_flip to true, this flips the image vertically. If you find the output image is upside down it is because you need to toggle render_target_v_flip.
Then place as child of the Viewport what you want to render.
Rendering
Next, you can read the texture form the Viewport, convert it to an image, and save it to a png. I'm doing this on a tool script attached to the Viewport, so I'll have a workaround to trigger the code from the inspector panel. My code looks like this:
tool
extends Viewport
export var save:bool setget do_save
func do_save(new_value) -> void:
var image := get_texture().get_data()
var error := image.save_png("res://output.png")
if error != OK:
push_error("failed to save output image.")
You can, of course, export a FILE path String to ease changing it in the inspector panel. Here I'm handing common edge cases:
tool
extends Viewport
export(String, FILE) var path:String
export var save:bool setget do_save
func do_save(_new_value) -> void:
var target_path := path.strip_edges()
var folder := target_path.get_base_dir()
var file_name := target_path.get_file()
var extension := target_path.get_extension()
if file_name == "":
push_error("empty file name.")
return
if not (Directory.new()).dir_exists(folder):
push_error("output folder does not exist.")
return
if extension != "png":
target_path += "png" if target_path.ends_with(".") else ".png"
var image := get_texture().get_data()
var error := image.save_png(target_path)
if error != OK:
push_error("failed to save output image.")
return
print("image saved to ", target_path)
Another option is to use ResourceSaver:
tool
extends Viewport
export var save:bool setget do_save
func do_save(new_value) -> void:
var image := get_texture().get_data()
var error := ResourceSaver.save("res://image.res", image)
if error != OK:
push_error("failed to save output image.")
This will only work from the Godot editor, and will only work for Godot, since you get a Godot resource file. Although I find interesting the idea of using Godot to generate images. I'm going to suggest going with ResourceSaver if you want to automate generating them for Godot.
About saving resources from tool scripts
In the examples above, I'm assuming you are saving to a resource path. This is because the intention is to use the output image as a resource in Godot. Using a resource path has a couple implications:
This might not work on an exported game (since the goals is improve the workflow, this is OK).
Godot would need to re-import the resource, but will not notice it changed.
We can deal with the second point from an EditorPlugin, if that is what you are doing, you can do this to tell Godot to scan for changes:
get_editor_interface().get_resource_filesystem().scan()
And if you are not, you can cheat by creating an empty EditorPlugin. The idea is to do this:
var ep = EditorPlugin.new()
ep.get_editor_interface().get_resource_filesystem().scan()
ep.free()
By the way, you will want to cache cache the EditorPlugin instead of making a new one each time. Or better yet, cache the EditorFileSystem you get from get_resource_filesystem.
Automation
Now, I'm aware that it can be cumbersome to have to place things inside the Viewport. It might be Ok for your workflow if you don't need to do it all the time.
But what about automating it? Well, regardless of the approach, you will need a tool script that makes a hidden Viewport, takes a Node, checks if it has a shader, if it does, it moves it temporarily to the Viewport, get the rendered texture (get_texture()) sets it as the texture of the Node, removes the shader, and returns the Node to its original position in the scene. Or instead of looking for a shader in the Node, always apply a shader to whatever Node, perhaps loaded as a resource instead of hard-coded.
Note: I believe you need to let an idle frame pass between adding the Node to the Viewport and getting the texture, so the texture updates. Or was it two idle frames? Well, if one does not work, try adding another one.
About making an EditorPlugin
As you know, you can create an addon from project settings. This will create an EditorPlugin script for you. There you can either add an option to the tools menu (with add_tool_menu_item), or add it to the tool bar of the editor (with add_control_to_container). And have it act on the current selection in the edited scene (you can either use get_selection, or overwrite the edit and handles methods). You may also want to make an undo entry for that, see get_undo_redo.
Or, alternatively you can have it keep track (or look for) the Nodes it has to act upon, and then work on the build virtual method, which runs when the project is about to run. I haven't worked with the build virtual method, so I don't know if it has any quirks to gotchas to be aware of.

NavigationManager's startNavigation() has blank map

I'm trying to use turn by turn navigation using SKNavigationManager's startNavigation(navigationSettings). Interestingly it works flawless in 'Simulation' mode but when I switch to 'Real' mode there is no map on the screen. It's just that the map is not drawn on screen, but the rest like annotations and other stuff are populated and working fine.
I've used SKToolsNavigatoinManager and it works fine, but I don't want to use it as it has a lot of UI interfaces which are not useful for my application.
Any help is appreciated.
Here is the settings and the navigationManager code I'm using
SKNavigationSettings navigationSettings = new SKNavigationSettings();
SKNavigationManager navigationManager = SKNavigationManager.getInstance();
navigationSettings.setNavigationType(SKNavigationSettings.SKNavigationType.REAL);
navigationSettings.setNavigationMode(SKNavigationSettings.SKNavigationMode.PEDESTRIAN);
navigationManager.setMapView(navMapView);
navigationManager.startNavigation(navigationSettings);
If i don't use the navigationManager.setMapView(navMapView); I get a different view.
1. This is how the screen looks like after I start navigation
2. This is how the screen looks like before navigation
The map is drawn to the screen its just centered at the point [0,0] which is in the middle of the Atlantic ocean therefore the screen is blue. To have the camera follow the current location you must do the following 2 steps:
Set follow positions to true on your SKMapView object: navMapView.getMapSettings().setFollowPositions(true);
Create a SKCurrentPositionProvider and set the SKCurrentPositionListener
SKCurrentPositionProvider positionProvider = new SKCurrentPositionProvider(activity);
positionProvider.setCurrentPositionListener(new SKCurrentPositionListener(){
#Override
public void onCurrentPositionUpdate(SKPosition currentPosition) {
SKPositionerManager.getInstance().reportNewGPSPosition(currentPosition);
}
});
positionProvider.requestLocationUpdates(true, true, false);

Fabricjs canvas objects not rendering properly

I need help with fabricjs, objects are not rendering properly while I clone and shrink to another canvas.
If I do only with text object there is not problem kindly look the below fiddle (after save)
enter code hereFIDDLE
If I load an image then the objects not aligning properly.
enter code hereFIDDLE
Kindly help to resolve form this.
Thank You.
Your problem for the image not respecting the zoom is that the image loads asyncronously. So you load from json, you do the zoom logic, some microseconds later the image finish loading and sets its own width and height.
Other than this you have to use zoom the right way.
Everyone is scaling manually and changing left and top using division or multiply with scale factor.
The good way is using
canvas.setZoom(scale);
This will save a lot of headaches to you.
$(function () {
scale = 0.5;
canvas1 = new fabric.Canvas('c1');
canvas1.setDimensions({
"width": canvas.getWidth() * scale,
"height": canvas.getHeight() * scale
})
var json = localStorage.getItem('save');
canvas1.loadFromJSON(json, function () {
canvas1.renderAll();
});
canvas1.setZoom(scale);
canvas1.renderAll();
});
chek updated fiddle
https://jsfiddle.net/asturur/Lep9w01L/11/

Phaser.js - how do I take an object out of a group?

I'm playing around with phasers invaders example game.
When the object is shot, instead of killing it I'm changing the sprite and moving it to the bottom of the screen. However, it can now be shot again. I don't want it to be shootable a 2nd time. I'm thinking that because the gamephysics are on the group 'aliens', there are probably two options.
a) Either I can take the single shot alien out of the group 'aliens' and hope that stops it from being shot a 2nd time.
b) Or there's some way of saying ' alien just shot = now protected from being shot again' , I tried the following to no avail.
alien.physicsBodyType = null;
This is my collision handler right now
function collisionHandler (bullet, alien) {
// When a bullet hits an alien we kill them both
bullet.kill();
alien.loadTexture("cured");
// move alien to bottom
var tween2 = game.add.tween(alien).to( { y: 300 }, 1000, Phaser.Easing.Linear.EaseIn, true);
tween2.onComplete.add(doNext, this);
tween2.start();
So, basically the changed sprite can still be shot at, I need to make it so it cannot be shot at.
I tried this.
game.world.add(happy);
It changed the position of the sprite and it was still shootable. Hmmm...
Is there a way to take collision off the single shot alien?
Ok, I figured out my answer, just deactivate the body of the sprite, you don't need to take it out of the group.
sprite.body.enable = false;
Where 'sprite' is the name of your actual sprite. Tested and works.

iPhone help with animations CGAffineTransform resetting?

Hi I am totally confused with CGAffineTransform animations. All I want to do is move a sprite from a position on the right to a position on the left. When it has stopped I want to "reset" it i.e. move it back to where it started. If the app exits (with multitasking) I want to reset the position again on start and repeat the animation.
This is what I am using to make the animation..
[UIImageView animateWithDuration:1.5
delay:0.0
options:(UIViewAnimationOptionAllowUserInteraction |
UIViewAnimationOptionCurveLinear
)
animations:^(void){
ufo.transform = CGAffineTransformTranslate(ufo.transform, -270, 100);
}
completion:^(BOOL finished){
if(finished){
NSLog(#"ufo finished");
[self ufoAnimationDidStop];
}
}];
As I understand it the CGAffineTransforms just visually makes the sprite look like it's moved but doesn't actually move it. Therefore when I try and "reset" the position using
ufo.center = CGPointMake(355, 70);
it doesn't do anything.
I do have something working, if I call
ufo.transform = CGAffineTransformTranslate(ufo.transform, 270, -100);
it resets. The problem is if I exit the app half way through the animation then when it restarts it doesn't necessarily start from the beginning and it doesn't go the the right place, it basically goes crazy!
Is there a way to just remove any transforms applied to it? I'm considering just using a timer but this seems silly when this method should work. I;ve been struggling with this for some time so any help would be much appreciated.
Thanks
Applying a transform to a view doesn't actually change the center or the bounds of the view; it just changes the way the view is shown on the screen. You want to set your transform back to CGAffineTransformIdentity to ensure that it looks like "normal." You can set it to that before you start your animation and set it to what you want it to animate to.

Resources