//Object 1: (draw event)
draw_text(x,y, global.Score);
draw_set_alpha(0.5);
//Object 2: (draw_event)
draw_text(x,y, global.highscore);
draw_set_alpha(1);
The problem is, that the drawn objects (without sprites) sometimes have the alpha from the other, or even ignores the "draw_set_alpha();" (The same in step-event)
When you use draw_set_alpha(), as well as other draw_set_.. methods, you change global settings for drawing everything after it across the entire project.
Take as a rule, revert such settings back, after you draw the needed thing. So, according to your code above, you should use this:
//Object 1: (draw event)
var prev_alpha = draw_get_alpha(); //getting current alpha settings
draw_set_alpha(0.5); // setting needed alpha
draw_text(x,y, global.Score); //drawing text with 0.5 alpha
draw_set_alpha(prev_alpha); // setting alpha setting back
// the same for the second object
//Object 2: (draw_event)
var prev_alpha = draw_get_alpha();
draw_set_alpha(1);
draw_text(x,y, global.highscore);
draw_set_alpha(prev_alpha);
Related
Can the measurement tool be scripted to measure a custom distance? Not an existing measurement, that is.
I would have thought it possible, but Abobe's documentation are sketchy
and there's not much info when it comes down to scripting the measurement tool. Or ruler, as it use to be known. More specifically a lack of examples using the ruler in a script.
Ideally I'd like to:
Script a measurement from x1,y1 to x2,y2
Determine its length, (preferably from a variable, not from a text file - see below)
Clear the ruler tool (so no ruler line appears)
Delete any measurements (so there are no recordings in the ruler window)
That's basic trig, right? But if you can't set the initial ruler then this is all for nothing.
The only thing on the list I've done is the last. :(
I stumble at the first hurdle not being able to set the ruler, which I thought would be app.activeDocument.recordMeasurements(); Only it gets returned as undefined or Unable to record measurements for selection.
As minimal working, this is pretty minimal:
// Let's stick to pixels as the units to make things easier.
// Switch off any dialog boxes
displayDialogs = DialogModes.ERROR; // OFF
// Get and set the units to pixels
var currentUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// delete existing measurements
app.measurementLog.deleteMeasurements(); // THIS WORKS!!
// call the source document
var srcDoc = app.activeDocument;
// Set array to record measurements
var rulerArr = [];
// Set ruler measurement
measure_it(x1,y1,x2,y2); // this a fictional function
// not even the ScriptListener records the ruler tool in a useful form
// var d = app.activeDocument.recordMeasurements(MeasurementSource.MEASURESELECTION, rulerArr); // Unable to record measurements for selection
// var d = app.activeDocument.recordMeasurements(MeasurementSource.MEASURESELECTION); // Unable to record measurements for selection
var d = app.activeDocument.recordMeasurements(); // undefined
var ruler = app.measurementLog; // Is an object!
alert(ruler.length); // undefined
// There's an option to export to a text file
// Is that the only way to get the measurements?
// Can't this be don't internally?
var f = "D:\\temp\\ruler.txt";
ruler.exportMeasurements(f, MeasurementRange.ACTIVEMEASUREMENTS)
alert(app.measurementLog);
// put the units back to how it was
app.preferences.rulerUnits = currentUnits;
// Set Display Dialogs back to normal
displayDialogs = DialogModes.ALL; // NORMAL
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!
I have an NSTextBlock subclass that has a specific backgroundColor set. Now when I add a custom paragraph style to a range of text like this
let block = MyTextBlock()
block.backgroundColor = myBackgroundColor
let pstyle = NSMutableParagraphStyle()
pstyle.textBlocks = [block]
attributedText.addAttribute(.paragraphStyle, value: pstyle, range: textRange)
// Append the attributed string to the text views textStorage ...
the text block is shown without a background color. I know that the text blocks works, because rectForLayout gets called, but when I try to override drawBackground it never gets called.
Do I have to do something else for NSTextBlocks to draw their background?
PS: Borders also seem to be ignored. I also tried to find a sample on Github, but that also doesn't draw any backgrounds, despite having a background color set.
After trying everything, I finally managed to get the background to show up, by setting
setValue(100, type: .percentageValueType, for: .width)
It seems that the drawing logic expects some value for the content size. Really nice documentation job there. This requirement is nowhere to be found.
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
I'm trying to draw what amounts to a screen-tone effect over an existing image, but I'd like to leave an area blank. Think of how spotlights in old games are sometimes done, where most of the image is darkened, and but part of it is the "normal" color.
To do this, I need my overlay to be transparent (since the original image has to show through). I'm also drawing this with wxDC.DrawCircle(...) (with a transparent brush), since it allows me to not draw over a circular area.
Problem is, the stipple (screen tone effect) isn't transparent, it's solid. I've tried just about everything I can think of, but nothing seems to work.
My current code is roughly like this:
const char* ScreenToneColor[] =
{
/* columns rows colors chars-per-pixel */
"3 3 2 1",
"X c Black",
"O c None",
/* pixels */
"OOO",
"OXO",
"OOO"
};
CustomPanel::CustomPanel(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(151, 151))
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
// MemberVariables
m_Stipple = wxBitmap(wxImage(ScreenToneColor));
m_ScreenTone = wxPen(*wxBLACK, 2 * VeryLargeRadius, wxPENSTYLE_STIPPLE);
m_ScreenTone.SetStipple(m_Stipple);
}
// Supplied with a wxAutoBufferedDC
void CustomPanel::Render(wxDC& dc)
{
dc.SetBrush(*wxGREEN_BRUSH);
dc.DrawRectangle(m_PanelRectange);
// "fade out" trimmed areas by drawing a ring.
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.SetPen(m_ScreenTone);
dc.DrawCircle(m_AnimatedCenter, VeryLargeRadius + m_VisibleRadius);
}
I've tried supplying the mask, using the different stipple masks (avoiding wxPENSTYLE_STIPPLE_MASK_OPAQUE), etc.
I'm on Windows 10 and compiling against wxWidgets 3.1, although the project is being built/run on other OSs, and possibly a lower library version.
wxDC doesn't support transparency with just the only exception of drawing bitmaps with alpha channel. If you want to do anything involving alpha, you need to use wxGraphicsContext and related classes. I'm not sure if GDI+ or Direct2D implementations of it currently handle this correctly, but after checking the code it seems like at least the former one should.