Here I want to write a script that can stabilize the time lapse sequence by adding Warp Stabilizer VFX, then followed by deflicker using DEFlicker Time Lapse, and finally render and export the video, which runs before sleeping so that it does not slow down my computer at working time. However, I cannot find the API that adds effects to a layer in AE scripting documentation, does anyone knows how to do this? thanks in advance!
You can add effects to the layers like this:
if (!theLayer.Effects.property("Warp Stabilizer")){ //add only if no such effect applied
var theEffect = theLayer.property("Effects").addProperty("Warp Stabilizer"); // the regular way to add an effect
}
To test it you can add it to selected layer, full code to apply it to the selected layer can look like this:
var activeItem = app.project.activeItem;
if (activeItem != null && activeItem instanceof CompItem) { // only proceeds if one comp is active
if (activeItem.selectedLayers.length == 1) { // only proceeds if one layer is selected
var theLayer = activeItem.selectedLayers[0];
if (!theLayer.Effects.property("Warp Stabilizer")){
var theEffect = theLayer.property("Effects").addProperty("Warp Stabilizer"); // the regular way to add an effect
}
}
}
Solution is based on adobe forum: https://forums.adobe.com/thread/1204115
Related
hoping someone can help. I am creating an app whereby the user will touch a series of images to rotate them. What I am trying to do. Is highlight the image once the user has rotated to a particular position.
Is this possible? If, so any tips greatly appreciated.
edit - ok here's an example instead!
First, the simplest way, based off the code example you just posted:
r1c1.setOnClickListener {
r1c1.animate().apply{ duration = 100 rotationBy(270f) }.start()
}
So the issue here is that you want to highlight the view when it's rotated to, say 90 degrees, right? But it has an animation to complete first. You have three options really
do something like if (r1c1.rotation + 270f == 90) and highlight now, as the animation starts, which might look weird
do that check now, but use withEndAction to run the highlighting code if necessary
use withEndAction to do the checking and highlighting, after the anim has finished
the latter probably makes the most sense - after the animation finishes, check if its display state needs to change. That would be something like this:
r1c1.animate().setDuration(100).rotationBy(270f).withEndAction {
// need to do modulo so 720 == 360 == 0 etc
if (r1c1.rotation % 360 == TARGET_ROTATION) highlight(r1c1)
}.start()
I'm assuming you have some way of highlighting the ImageViews and you weren't asking for ways to do that!
Unfortunately, the problem here is that if the user taps the view in the middle of animating, it will cancel that animation and start a new one, including the rotationBy(270) from whatever rotation the view currently happens to be at. Double tap and you'll end up with a view at an angle, and it will almost never match a 90-degree value now! That's why it's easier to just hold the state, change it by fixed, valid amounts, and just tell the view what it should look like.
So instead, you'd have a value for the current rotation, update that, and use that for your highlighting checks:
# var stored outside the click listener - this is your source of truth
viewRotation += 270f
# using rotation instead of rotationBy - we're setting a specific value, not an offset
r1c1.animate().setDuration(100).rotation(viewRotation).withEndAction {
// checking our internal rotation state, not the view!
if (viewRotation % 360 == TARGET_ROTATION) highlight(r1c1)
}.start()
I'm not saying have a single rotation var hanging around like that - you could, but see the next bit - it's gonna get messy real quick if you have a lot of ImageViews to wrangle. But this is just to demonstrate the basic idea - you hold your own state value, you're in control of what it can be set to, and the View just reflects that state, not the other way around.
Ok, so organisation - I'm guessing from r1c1 that you have a grid of cells, all with the same general behaviour. That means a lot of repeat code, unless you try and generalise it and stick it in one place - like one click listener, that does the same thing, just on whichever view it was clicked on
(I know you said youre a beginner, and I don't like loading too many concepts on someone at once, but from what it sounds like you're doing this could get incredibly bloated and hard to work with real fast, so this is important!)
Basically, View.onClickListener's onClick function passes in the view that was clicked, as a parameter - basically so you can do what I've been saying, reuse the same click listener and just do different things depending on what was passed in. Instead of a lambda (the code in { }, basically a quick and dirty function you're using in one place) you could make a general click listener function that you set on all your ImageViews
fun spin(view: View) {
// we need to store and look up a rotation for each view, like in a Map
rotations[view] = rotations[view] + 270f
// no explicit references like r1c1 now, it's "whatever view was passed in"
view.animate().setDuration(100).rotation(rotations[view]).withEndAction {
// Probably need a different target rotation for each view too?
if (rotations[view] % 360 == targetRotations[view]) highlight(view)
}.start()
}
then your click listener setup would be like
r1c1.setOnClickListener { spin(it) }
or you can pass it as a function reference (this is already too long to explain, but this works in this situation, so you can use it if you want)
r1c1.setOnClickListener(::spin)
I'd recommend generating a list of all your ImageView cells when you look them up (there are a few ways to handle this kind of thing) but having a collection lets you do things like
allCells.forEach { it.setOnClickListener(::spin) }
and now that's all your click listeners set to the same function, and that function will handle whichever view was clicked and the state associated with it. Get the idea?
So your basic structure is something like
// maybe not vals depending on how you initialise things!
val rotations: MutableMap<View, Float>
val targetRotations: Map<View, Float>
val allCells: List<ImageView>
// or onCreateView or whatever
fun onCreate() {
...
allCells.forEach { it.setOnClickListener(::spin) }
}
fun spin(view: View) {
rotations[view] = rotations[view] + 270f
view.animate().setDuration(100).rotation(rotations[view]).withEndAction {
val highlightActive = rotations[view] % 360 == targetRotations[view]
highlight(view, highlightActive)
}.start()
}
fun highlight(view: View, enable: Boolean) {
// do highlighting on view if enable is true, otherwise turn it off
}
I didn't get into the whole "wrapper class for an ImageView holding all its state" thing, which would probably be a better way to go, but I didn't want to go too far and complicate things. This is already a silly length. I might do a quick answer on it just as a demonstration or whatever
The other answer is long enough as it is, but here's what I meant about encapsulating things
class RotatableImageView(val view: ImageView, startRotation: Rotation, val targetRotation: Rotation) {
private var rotation = startRotation.degrees
init {
view.rotation = rotation
view.setOnClickListener { spin() }
updateHighlight()
}
private fun spin() {
rotation += ROTATION_AMOUNT
view.animate().setDuration(100).rotation(rotation)
.withEndAction(::updateHighlight).start()
}
private fun updateHighlight() {
val highlightEnabled = (rotation % 360f) == targetRotation.degrees
// TODO: highlighting!
}
companion object {
const val ROTATION_AMOUNT = 90f
}
}
enum class Rotation(var degrees: Float) {
ROT_0(0f), ROT_90(90f), ROT_180(180f), ROT_270(270f);
companion object {
// just avoids creating a new array each time we call random()
private val rotations = values()
fun random() = rotations.random()
}
}
Basically instead of having a map of Views to current rotation values, a map of Views to target values etc, all that state for each View is just bundled up into an object instead. Everything's handled internally, all you need to do from the outside is find your ImageViews in the layout, and pass them into the RotatableImageView constructor. That sets up a click listener and handles highlighting its ImageView if necessary, you don't need to do anything else!
The enum is just an example of creating a type to represent valid values - when you create a RotatableImageView, you have to pass one of these in, and the only possible values are valid rotation amounts. You could give them default values too (which could be Rotation.random() if you wanted) so the constructor call can just be RotatableImageView(imageView)
(you could make more use of this kind of thing, like using it for the internal rotation amounts too, but in this case it's awkward because 0 is not the same as 360 when animating the view, and it might spin the wrong way - so you pretty much have to keep track of the actual rotation value you're setting on the view)
Just as a quick FYI (and this is why I was saying what you're doing could get unwieldy enough that it's worth learning some tricks), instead of doing findViewById on a ton of IDs, it can be easier to just find all the ImageViews - wrapping them in a layout with an ID (like maybe a GridLayout?) can make it easier to find the things you want
val cells = findViewById<ViewGroup>(R.id.grid).children.filterIsInstance<ImageView>()
then you can do things like
rotatables = cells.map { RotatableImageView(it) }
depends what you need to do, but that's one possible way. Basically if you find yourself repeating the same thing with minor changes, like the infomercials say, There Has To Be A Better Way!
Following the example on the website: https://vega.github.io/editor/#/examples/vega-lite/interactive_bar_select_highlight
I want to programmatically set the selections via signals. I realize that I could emulate a click by doing the following
VEGA_DEBUG.view.signal("select_tuple", {"unit":"","fields":[{"type":"E","field":"_vgsid_"}],"values":[1]})
However, I cannot proceed to select another, e.g., the shift select of the 2
VEGA_DEBUG.view.signal("select_tuple", {"unit":"","fields":[{"type":"E","field":"_vgsid_"}],"values":[2]})
This makes sense, since only shift-click accumulates the state.
I tried modifying the accumulated signal
VEGA_DEBUG.view.signal("select", {"_vgsid_":[1,2],"vlMulti":{"or":[{"_vgsid_":1},{"_vgsid_":2}]}})
However, this does not help. Is this not possible? I understand that a custom solution may be possible in hand-rolled vega, as opposed to that compiled from vega-lite.
Thanks.
Just need to set VEGA_DEBUG.view.signal("select_toggle", true) before adding the new select!!
After much research I made this example of how to change the vega-lite brush programmatically
https://observablehq.com/#john-guerra/update-vega-lite-brush-programmatically
Using #koaning example this stack overflow question I figured that you can change the brush by updating "brush_y" (assuming that your selection is called brush) or change the selection using "brush_tuple" (which doesn't seem to update the brush mark)
viewof chart = {
const brush = vl.selectInterval("brush").encodings("y");
const base = vl
.markBar()
.select(brush)
.encode(
vl.x().count(),
vl.y().fieldQ("Horsepower"),
vl.color().if(brush, vl.value("steelblue")).value("gray")
)
.height(maxY);
return base.data(data).render();
}
update = {
// From https://codepen.io/keckelt/pen/bGNQPYq?editors=1111
// brush_y -> brush_tuple -> brush
// Updates on pixels
chart.signal("brush_y", [by0, maxY / 2]);
await chart.runAsync();
}
Crossposting here in case it might be useful for anyone
In titanium it is possible to hide a view like so:
$.foo.hide()
or
$.foo.visible = false
However, in both cases the object still seems to take physical space. It is just invisible. In other words it is similar to the CSS property visibility: hidden.
I want it so that it disappears and take no physical space in terms of width or height, so it's similar to the CSS property display: none
How can I do this?
The best hacky solution I have is the following:
$.foo.width = 0;
$.foo.height = 0;
$.foo.left = 0;
$.foo.right = 0;
But that means when I want to make it visible again, I have to set all those properties back to their original values which is a pain and hard to maintain.
First of all, don't afraid of doing some hard coding ;)
Coming to your query, yes, this is true that hiding a view just hide it from UI, but physical-space is still there.
To do what you want, you will need to either remove view on hide & create it on show, or you can use absolute layout in some tricky way.
Other way could be to animate this view using transform property like this:
// on hide
$.foo.animate({
duration : 100,
transform : Ti.UI.create2DMatrix({scale:0})
}, function () {
$.foo.visible = false;
});
// on show
$.foo.visible = true; // we need to make it visible again before resetting its UI state since we hid it after completion of animation in above code
$.foo.animate({
duration : 100,
transform : Ti.UI.create2DMatrix() // passing empty matrix will reset the initial state of this view
});
OR
this could also work but never tried this:
// on hide
$.foo.transform = Ti.UI.create2DMatrix({scale:0});
$.foo.visible = false;
// on show
$.foo.visible = true;
$.foo.transform = Ti.UI.create2DMatrix();
I'm using cytoscape.js with the arbor layout. Is there a way to manually stop the layout rendering ? In the doc i saw a 'layoutstop' event but no way to actually stop the layout.
Thanks
Here is how I worked around the problem if someone's interested : I just put a global stop_layout var in the stableEnergy function. Ugly but it works. Yay!
var stop_layout = false;
layout_params = {
name: 'arbor',
stableEnergy: function(energy){
var e = energy;
return (e.max <= 0.5) || (e.mean <= 0.3) || stop_layout;
}
};
// Then change the stop_layout value when you want to run or stop layout processing
layoutstop is an event to indicate that the layout has stopped running. Arbor includes a maxSimulationTime option so you can stop the layout early: http://cytoscape.github.io/cytoscape.js/#layouts/arbor
I have a view that displays several nodes. I want to place node form below each displayed node. Both node_add and drupal_get_form directly in template.php works fine, but I get forms with same form ID of NODETYPE_node_form and validation and submitting does not work as expected.
If you had to put several node forms on one page, what would be your general approach?
Progress so far...
in template.php while preprocessing node
$author_profile and $content is set before.
$unique = $vars['node']->nid;
$node = new StdClass();
$node->uid = $vars['user']->uid;
$node->name = $vars['user']->name;
$node->type = 'review';
$node->language = '';
$node->title = t('Review of ') . $vars['node']->realname . t(' by ') . $vars['user']->realname . t(' on ') . $content->title;
$node->field_review_to_A[0]['nid'] = $nodeA->nid;
$node->field_review_to_B[0]['nid'] = $vars['node']->nid;
$node->field_review_to_profile[0]['nid'] = $author_profile->nid;
if(!function_exists("node_object_prepare")) {
include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
}
//$vars['A_review_form'] = drupal_get_form('review_node_form', $node);
$vars['A_review_form'] = mymodule_view($node, $unique);
in mymodule module
function mymodule_view($node, $unique) {
if(!function_exists("node_object_prepare")) {
include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
}
$output = drupal_get_form('review_node_form_' . $unique, $node);
return $output;
}
function mymodule_forms($form_id, $args) {
$forms = array();
if (strpos($form_id, "review_node_form_") === 0) {
$forms[$form_id] = array('callback' => 'node_form');
}
return $forms;
}
function mymodule_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node']) && $form_id != $form['type']['#value'] .'_node_form' && $form['type']['#value'] == 'review') {
$type = content_types($form['#node']->type);
if (!empty($type['fields'])) {
module_load_include('inc', 'content', 'includes/content.node_form');
$form = array_merge($form, content_form($form, $form_state));
}
$form['#pre_render'][] = 'content_alter_extra_weights';
$form['#content_extra_fields'] = $type['extra'];
//$form['#id'] = $form_id;
//$form['#validate'][0] = $form_id . '_validate';
$form['title']['#type'] = 'value';
$form['field_review_to_A']['#type'] = 'value';
$form['field_review_to_B']['#type'] = 'value';
$form['field_review_to_profile']['#type'] = 'value';
}
}
Questions
My take on summarizing unclear questions...
Is this good general approach for displaying multiple node forms on same page?
Is it OK to copy/paste code from content modules content_form_alter function in function mymodule_form_alter? Will it not brake things if content module is updated?
Should i set $form['#id']? Without it all forms has same HTML form ID of node_form, with it ID is unique, like review_node_form_254. Thing is that there is no difference of how form is submitted. Setting $form['#validate'][0] does not seem to influence things too. Maybe I should set $form[button]['#submit'][0] to something else? Now its node_form_submit.
Why validation does not work even with unique form id and form validate function? If i submit last form without required field all previous forms gets particular fields red. should I make my own validation function? what level - form or field? Any tips on where to start?
You need to implement hook_forms() to map different ids to the same builder function.
The NODETYPE_node_form ids you mention are already an example of this mechanism, as they are all mapped to the same builder function (node_form()) within the node modules node_forms() implementation.
You can find links to more examples in the 'Parameters' explanation off the drupal_get_form() function.
This was exceptionally useful to me.
Documentation on all the drupal APIs is so lacking - I was tearing my hair out. The crucial bit for me, that I don't think is covered anywhere else on the net:
CCK adds its fields to your form through hook_form_alter() . But it does this based on the form_id. So if the form ID is different (cause you want multiple ones on the same page), you need to replicate a bit of the CCK code to add the fields to your form regardless.
That is what this does brilliantly.
I really did not dig to the bottom of it, but it seems to me that you pretty much did all the relevant digging by yourself.
From what I understand by inspecting the code only, you are right in thinking that content_form_alter() is the show-stopper.
Maybe this is a naïve suggestion, but what about writing your own implementation of hook_form_alter() starting from the content_form_alter() code but changing the conditions that make the alteration to occur? I am thinking to something along these lines:
function modulename_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node']) &&
stripos($form_id, $form['type']['#value'] .'_node_form')) {
...
}
}
I did not actually test the code above, but I hope it is self-explenatory: you actually trigger the changes for a give customised type of content if MYCCKTYPE_node_form is a substring of the actual form_id (es: MYCCKTYPE_node_form_234).
Hope this helps at least a bit... Good luck! :)
EDIT: TWO MORE THINGS
It just occurred to me that since your custom implementation of hook_form_alter() will live aside the CCK one, you would like to add a check to avoid the form to be modified twice something like:
&& $form_id != $form['type']['#value'] .'_node_form'
The other way you might try to implement this by not using CCK but implementing you custom type programmatically (this might even be an advantage if you plan to use your module on various different sites).