createjs combine 2 shapes in a mask - masking

I have a symbol S1 with two shapes (lets say sh0 and sh1). On the stage I have an instance of another symbol mc. At run time, I will create an instance mc1 of the symbol S1. Using createjs, how can I use mc1 as a mask for mc?

I assume when you say "symbol", you mean a graphic or MovieClip in Adobe Animate. Unfortunately, you can only use a CreateJS "Shape" as a mask directly. There are a few options:
Combine the shapes into one yourself.
Combine the instructions. This is a bit dirty, but you could in theory concat the graphic instructions from one shape into another. I suspect this would have issues if the Shape instances have different x/y positions.
symbol.shape1.graphics._instructions.concat(symbol.shape2.graphics._instructions);
Cache the symbol as use it as a Mask with AlphaMaskFilter. The example in the documents should get you what you want.
var box = yourSymbol;
box.cache(0, 0, 100, 100);
var bmp = new createjs.Bitmap("path/to/image.jpg");
bmp.filters = [
new createjs.AlphaMaskFilter(box.cacheCanvas)
];
bmp.cache(0, 0, 100, 100);
The 3rd is probably your best option, but it is limiting and can be performance intensive due to the use of the filter (especially if content changes and you have to update it constantly).
Feel free to post more details on what you are working with in order to get a better recommendation.
Cheers.

Related

Using collections to create random buildings with Blender

I had the idea of creating a fantasy city, and to avoid having the same house over and over, but not have to manually create hundreds of houses I was thinking on creating collections like "windows", "doors", "roofs", etc, and then create objects with vertex's assigned to specific groups with the same names ("windows" vertex groups, "doors" vertex groups, etc), and then have blender pick for each instance of a house a random window for each of the vertex in the group, same for doors, roofs, etc.
Is there a way of doing this? (couldn't find anything online), or do I need to create a custom addon? If so, any good reference or starting point where something close to this is done?
I've thought of particle systems, or child objects, but couldn't find a way to attach to the vertex a random part of the collection. Also thought of booleans, but it doesn't have an option to attach to specific vertex, nor to use collections. So I'm out of ideas of how to approach this.
What I have in mind:
Create basic shape, and assign vertex to the "windows" vertex group:
https://i.imgur.com/DAkgDR3.png
And then have random objects within the "Windows" collection attached to those vertex, as either a particle or modifier:
https://i.imgur.com/rl5BDQL.png
Thanks for any help :)
Ok, I've found a way of doing this.
I'm using 3 particle systems (doors, roofs and windows), each using vertex as emitters, and using vector groups to define where to display one of each the different options.
To avoid the particle emitter to put more than one object per vertex, I created a small script that counts the number of vertex of each vertex group and updates each of the particle system Emission number accordingly.
import bpy
o = bpy.data.objects["buildings"]
groups = ["windows", "doors", "roofs"]
for group in groups:
vid = o.vertex_groups.find(group)
vectors = [ v for v in o.data.vertices if vid in [ vg.group for vg in v.groups ] ]
bpy.data.particles[group].count = len(vectors)
I've used someone's code from stack overflow for counting the number of vectors in a vector group, but can't find again the link to the specific question, so if you see your code here, please do comment and I'll update my answer with the proper credit.

How to link two ROIs on two different images

I wrote a little program that copies the frame and position of a ROI from an image to an other image of the same size.
What I want to do now is to connect the two ROIs in way that when I move one ROI the other one is moving accordingly.
On Dave's mitchell DM scripting website, I found that he used the function ConnectObject. but he does not explain how it works.
I read the DM3's documentation and I couldn't find any information about that function.
There are two concepts here which would work. You can use one of two methods:
1) Use "ConnectObject" to attach some functionality to when a ROI is moved, i.e. when you move ROI 1 it "triggers" code which you can use to update other rois.
2) Use "ImageDisplayListeners" to attach functionality to when any ROI on a specific imageDisplay is moved,
i.e. when a ROI an image A is moved it triggers code which you can use to update other rois.
You will find example code in this answer.
For simple things there is another option:
Adding the identical ROI to more than one image-display:
In this case, the ROIs are "linked" automatically, because they really are only a single object in memory (but displayed on two displays.) Changing one will change the other.
However, this linkage is "lost" if you save/load the images, because when you load the image, all ROIs (in memory) are newly created. Here is some simple example code:
image img1, img2
GetTwoLabeledImagesWithPrompt("Select two images of same size.", "Select", "Source", img1, "Destination", img2 )
imageDisplay disp1 = img1.ImageGetImageDisplay( 0 )
imageDisplay disp2 = img2.ImageGetImageDisplay( 0 )
number nR = disp1.ImageDisplayCountROIs()
for ( number i = 0; i<nR; i++ )
{
ROI theROI = disp1.ImageDisplayGetROI(i)
disp2.ImageDisplayAddROI(theROI)
}

How do I make multiple copies of a set of polygons in a Vertex Buffer Array?

In OpengL 1, in Visual Basic with OpenTK, if I want a hundred cubes all arranged in circle i'd write
glRef = GL.GenLists(1)
GL.NewList(glRef, ListMode.Compile)
GL.Begin(PrimitiveType.Traingles)
GL.Vertex3....for the vertices of a cube
GL.End()
GL.EndList()
which would give me glRef as a handle with which I could do
For i = 0 to 100
GL.PushMatrix()
GL.Rotate(3.6*i, 0, 0, 1)
GL.Translate(5.0, 0.0, 0.0)
GL.CallList(glRef)
GL.PopMatrix()
Next
and get a hundred cubes all arranged in a circle.
How do I do the same sort of thing in Open GL 2.0 or higher with Vertex Buffer Objects?
I start off with
GL.GenBuffer(VBOid)
Dim VertexArray() As Single = {....for the vertices of a cube }
then do some binding of it to a vertex buffer
GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid(0))
GL.BufferData(BufferTarget.ArrayBuffer, SizeOf(GetType(Single)) * VertexArray.Count, VertexArray, BufferUsageHint.StaticDraw)
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, False, 0, VertexArray)
and then in my draw routine I do something along the lines of
GL.EnableClientState(ArrayCap.VertexArray)
GL.BindBuffer(BufferTarget.ArrayBuffer, PrimitiveID(0))
GL.DrawElements(PrimitiveType.Triangles)
but at this point adding a second DrawBuffer command together with transforms doesn't seem to create me a second cube. I've been bashing my head against a wall, looking all over the internet and I can't find a straight forward reference which tells me how to do it, or even confirmation that it's possible.
Is this not the way its supposed to work, am I just supposed to send a hundred sets of cube vertices, or is there a way to copy a vertex buffer object and apply transforms to it? (Or is I'm probably doing it wrong somewhere and I need to go on a bug hunt - any tips for that would be helpful)
I don't think GL.DrawBuffer is the correct command in this place. It is used to specify in the context of FBOs which attachment points can be written.
Since you try to draw a VBO here, I would expect the use of GL.DrawArrays or GL.DrawElements.

Cannot change polygon 'size' every repeat in Builder

I'm using Builder v1.80.06
I can vary the position of a polygon every repeat easily enough
e.g. I have a Positions list
positions=[[1,1],[1.1,0.9],...]
and in the 'Position field' have :
$positions[0]
and then change it's value in a code block on each repeat.
BUT I want to vary the size in a similar manner with a $sizes list but get an error.
Looking at the generated code, the problem is at the object creation stage. the code generated is:
for a hard coded polygon (ie ok)
polygon_1 = visual.Rect(win=win, name='polygon_1',
width=[1.5, .2][0], height=[1.5, .2][1],
ori=0, pos=[0, -0.6],
lineWidth=1, lineColor=[1,1,1], lineColorSpace=u'rgb',
fillColor=[0,1,0], fillColorSpace=u'rgb',
opacity=1,interpolate=True)
for one populated by a variable (not working):
polygon_2= visual.Rect(win=win, name='polygon_2',
width=1.0[0], height=1.0[1],
ori=0, pos=[0,0],
lineWidth=1, lineColor=[1,1,1], lineColorSpace=u'rgb',
fillColor=[1,0,0], fillColorSpace=u'rgb',
opacity=1,interpolate=True)
It complains (rightly) that 1.0[0] makes no sense on the width and height parameters
Even though I have my sizes list instantiated in a code block right at the beginning of the experiment instead of reading $sizes[0] a default float value of 1.0 is used.
Any other suggestions for how to vary the polygon size dynamically at runtime using builder?
I could just take the generated code and drop it into coder I suppose and fix the problem but I want to hand this over to a researcher so would like for them to be able to maintain it.
thanks,
If you set size to be a tuple/list with a pair values [1.2,1.5] or [1,1] does that not fix it?
When you change attributes at runtime, just change the attribute of an existing stimulus instead of instantiating a full new stimulus. The latter is quite heavy on ressources, causing unreliable timing. So do
stim = visual.Rect(win) # instantiation, ressource heavy
stim.attribute = newValue # change attribute. lighter.
I can think of two ways you could do it in a pretty neat way. The first is to set width and height explicitly instead of the size attribute, but using a size-like value. So (removing all parameters not of interest):
polygon_2 = visual.Rect(win)
# Unpack the x,y-sizes to the stimulus .width and .height attributes
newSize = (1.5, 0.2)
polygon_2.width, polygon_2.height = newSize
The second, if the size attribute is really important to use, is to use the Polygin with edges=4 to make it a rectangle:
polygon_2 = visual.Polygon(win=win, edges=4, size=(1.5, 0.2))
# Setting size
polygon_2.size = (0.8, 0.4)
Do try Jon's suggestion first. But the idea with visual.Rect and visual.Circleis to use substitute Polygon's size and vertices for something more relevant. So size can do unexpected things if width/height etc. are not 1.

In Gimp script-fu, how can you access QuickMask functionality?

In the Gimp GUI, the QuickMask is very useful for many things, but this functionality doesn't seem to be directly available through script-fu. No obvious equivalents were apparent to me in the procedure browser.
In particular, putting the (value/gray) pixels of a layer into the selection mask is the basic thing I need to do. I tried using gimp-image-get-selection to get the selection channel's id number, then gimp-edit-paste into it, but the following anchor operation caused Gimp to crash.
My other answer contains the "theoretical" way of doing it - however, the O.P. found a bug in GIMP, as of version 2.6.5, as can be seem on the comments to that answer.
I got a workaround for what the O.P. intends to do: paste the contents of a given image layer to the image selection. As denoted, edit-copy -> edit-paste on the selection drawable triggers a program crash.
The workaround is to create a new image channel with the desired contents, through the copy and paste method, and then use gimp-selection-load to make the selection equal the channel contents:
The functions that need to be called are thus (I won't paste scheme code, as I am not proficient in all the parenthesis - I did the tests using the Python console in GIMP):
>>> img = gimp.image_list()[0]
>>> ch = pdb.gimp_channel_new(img, img.width, img.height, "bla", 0, (0,0,0))
>>> ch
<gimp.Channel 'bla'>
>>> pdb.gimp_edit_copy(img.layers[0])
1
>>> pdb.gimp_image_add_channel(img, ch, 0)
>>> fl = pdb.gimp_edit_paste(ch, 0)
> >> fl
<gimp.Layer 'Pasted Layer'>
>>> pdb.gimp_floating_sel_anchor(fl)
>>> pdb.gimp_selection_load(ch)
Using QuickMask through the User interface is exactly equivalent to draw on the Selection, treating the selection as a drawable object.
So, to use the equivalent of "quickmask" on script-fu all one needs to is to retrieve the Selection as a drawable and pass that as a parameter to the calls that will modify it -
And to get the selection, one just have to call 'gimp-image-get-selection'