PDA

View Full Version : Binding Images in Controls



Nickademus
April 21st, 2017, 00:11
How do you set the image in an imagecontrol? It doesn't seem to have a datasource variable.

Moon Wizard
April 21st, 2017, 00:15
There is no API to set an image to an imagecontrol. You can only specify the field by "name" attribute or by "source" attribute in the main control tag.

Regards,
JPG

Nickademus
April 21st, 2017, 00:23
What field are you specifying? And what is the main control? The imagecontrol sits in a window (that can have a datasource), but it doesn't have any kind of interactions other than modifications to the tokens and grid and stuff. The reference manual has an imagecontrol that is created dynamically in a window that contains all the data for the page block, but I can't find the code where it grabs the image file from the block: "<image type="image"><bitmap>[Only used for image blocks. Local file path to image within the module.]</bitmap></image>"

Nickademus
April 21st, 2017, 11:04
So looking at the reference manual code, the image block creates an imagecontrol with the name of "image". The wiki says that an imagecontrol will be bound to the database if the window has a datasource. So I wonder if it is a coincidence that the window creating the imagecontrol for the block has a variable called "image" that holds the file location for an image or if this is how FG knows where in the database the image data is.

Would this mean that in order to create an imagecontrol that displays an image in the campaign the window would have a datasource of "image" and the created imagecontrol would have a name that matches the node name of the specific image, i.e. "id-00001"?

Moon Wizard
April 21st, 2017, 21:05
If you are creating the imagecontrol dynamically, then the control must have the same name as the data field.
If you are specifying the imagecontrol in XML (like the imagewindow class), then the source attribute is used, or the name attribute (if source not specified).

The data field for the image control must be a child of the database node which the campaign window uses, and have the control and the image data field must have the same name. (i.e. "image" for reference manual example, and also in the imagewindow class)

Regards,
JPG

Nickademus
April 21st, 2017, 21:33
Alright, thanks. I think I know how to get it to do what I want.

Nickademus
April 21st, 2017, 22:44
Nope, can't get this to work. There is some piece of information that I don't have. It keeps creating a control detailed as "imagecontrol = { x,y,w,h = 0,0,0,0 }" and getImageSize returns 200, 200 which isn't the size of the image. I don't think it is getting the actual image that I'm feeding it.

For a dynamic imagecontrol that displays the first image in the campaign, which name should be used to match the "data field":
1) image.id-00001
2) .image.id-00001
3) id-00001
4) id-00001.image
5) id-00001.image.bitmap
6) image
7) bitmap

And what datasource should the window have that it is created in?

Moon Wizard
April 22nd, 2017, 22:04
The imagecontrol will not create a database node or allow an image to be set, it only uses an existing database node. Otherwise, it creates a drawing. The data must already exist in the campaign database or module.

For example, here is a valid image record from a sample campaign:


<image>
<id-00001>
<image type="image">
<bitmap>images/cathedral_1stfloor.jpg</bitmap>
</image>
<name type="string">Cathedral Ground Floor</name>
</id-00001>
</image>


The link to access in an imagewindow window class would be:
Interface.openWindow ("imagewindow", "image.id-00001");

Within the imagewindow window class in CoreRPG, the imagecontrol is defined as:
<imagecontrol name="image">
<bounds>21,93,-27,-29</bounds>
<indicators availability="image_sent" locked="image_locked" loading="image_loading" zoom="image_zoom" shortcuts="image_shortcuts" />
<default snap="on" drawingsize="500,500" />
<script file="campaign/scripts/image.lua" />
</imagecontrol>

Regards,
JPG

Bidmaron
April 23rd, 2017, 02:35
MW, do you know if the inability to add your own images in your code that are not in image folder will be removed in FGU? I'm glad to see SW kind of fixed that in reference material, but it would be nice to see this limitation go away.

Nickademus
April 23rd, 2017, 05:15
The imagecontrol will not create a database node or allow an image to be set, it only uses an existing database node. Otherwise, it creates a drawing. The data must already exist in the campaign database or module.

For example, here is a valid image record from a sample campaign:


<image>
<id-00001>
<image type="image">
<bitmap>images/cathedral_1stfloor.jpg</bitmap>
</image>
<name type="string">Cathedral Ground Floor</name>
</id-00001>
</image>


The link to access in an imagewindow window class would be:
Interface.openWindow ("imagewindow", "image.id-00001");

Within the imagewindow window class in CoreRPG, the imagecontrol is defined as:
<imagecontrol name="image">
<bounds>21,93,-27,-29</bounds>
<indicators availability="image_sent" locked="image_locked" loading="image_loading" zoom="image_zoom" shortcuts="image_shortcuts" />
<default snap="on" drawingsize="500,500" />
<script file="campaign/scripts/image.lua" />
</imagecontrol>

Regards,
JPG

Thank you for the information, but I has already seen this. What I'm trying to do is more like the imagecontrol in the reference manual: a control created dynamically inside a subwindow using an existing database node. I'll have to take a closer look at the reference manual code to see where the image is being assigned. I know that the control is named "image" and that is most likely pointing to the image variable of the reference block. I need to see how the window that contains the image variable is made before it is passed to the function that creates the control.

Nickademus
April 23rd, 2017, 05:18
MW, do you know if the inability to add your own images in your code that are not in image folder will be removed in FGU? I'm glad to see SW kind of fixed that in reference material, but it would be nice to see this limitation go away.

The images in the reference manual come from the module of the reference manual. You can already access those with the Interface.openWindow by using the module name in the data source. The only issue I'm seeing is the inability to open images in a subwindow rather than a top-level window (which is probably due to my lack of understanding rather than a limitation of the program). There isn't really an inability to remove in FGU.

Bidmaron
April 23rd, 2017, 14:46
Nickademus, give up. The engine won't support what you are trying to do. If I remember rightly, they got it working in references by co-opting token-type data and logic. You are just going to have to wait until FGU or they decide to backlit this into current FG.

I have never understood why they did not provide a control that lets you specify a file name to an image file, but we (I at least) have been asking for it for almost ten years now. There is currently no way outside a reference module to imbed binary image data in a module or fg database, but a file name would be possible. They have just not done it for some reason.

Nickademus
April 23rd, 2017, 17:24
Nickademus, give up. The engine won't support what you are trying to do.

Nothing personal but I've heard this before. I tend to find ways regardless.

Bidmaron
April 23rd, 2017, 18:12
Let me know if you do. Only way I know to approximate it is tokens and bitmap attachments (can't think of control term and away from computer). Both have significant problems.

Moon Wizard
April 24th, 2017, 10:14
Bidmaron,
You can load images dynamically, but only by adding to the campaign images folder. We're still working on what this might look like in FGU, depending on how much we can support tiling and other map features.

Also, we have both the token and image data types working in the reference manual windows. Once the image data node is defined in the data (campaign or module), it's just a matter of making sure it's a child node for the window that contains the imagecontrol.

Nickademus,
In the referencemanual, there is a list control with a data node of "blocks". (See template_ref.xml:list_referencemanualpage_blocks; ref_manual.xml:referencemanualpagecontent:blocks and ref/scripts/ref_blocklayoutmanager.lua) This windowlist runs a script that iterates through each child window (something like "blocks.id-00001"), and dynamically instantiates controls in each of the child windows based on the data nodes under the child window node. (such as "image")

Regards,
JPG

Bidmaron
April 25th, 2017, 04:02
Yep, got the images folder thing, MW. Can you please let us specify an image file name in lua code in FGU? I am not sure why SW never would let us do that in the current engine. I am sure there must be a great reason, but I just hope all images don't have to be in the images folder for FGU.

Moon Wizard
April 25th, 2017, 06:30
You can't access files directly from the ruleset Lua script for security reasons.

Regards,
JPG

Nickademus
April 25th, 2017, 10:29
I don't mind having to have the image in the campaign folder. What is causing me problems is that the imagecontrol requires the containing window to have a datasource. I'm trying to display an image in a subwindow that isn't directly linked to the database. Going to have to come up with a workaround (I wonder if you can make subwindows dynamically...).

Bidmaron
April 25th, 2017, 18:34
MW, what is the difference whether say an icon resource is statically defined or defined at runtime? How is a dynamic resource a security problem?

I get it that accesing files directly is problematic, but where is the risk for read access to a file through a resource?

Nickademus
April 25th, 2017, 20:29
I imagine it has something to do with being able to make an extension that pulls images out of an encrypted adventure and put it into a custom window that allows the image to be exported into a new (non-encrypted) module. Something like that.

How do you define icons at runtime?

Moon Wizard
April 26th, 2017, 00:25
You can't define icons at runtime. They can only be defined as part of a ruleset or extension. Similarly for frames, templates, dice and window classes.

Regards,
JPG

Bidmaron
April 26th, 2017, 02:31
MW, I am not trying to be a pain but how please does specifying a graphic resource at run time violate security? Especially if it is only for an input ?

damned
April 26th, 2017, 04:53
MW, I am not trying to be a pain but how please does specifying a graphic resource at run time violate security? Especially if it is only for an input ?

Being able to access files from anywhere on the Harddrive via a script?
Sounds like a security risk to me...

Nickademus
April 26th, 2017, 11:10
It's not accessing files on the harddrive. It's accessing the <image> node of the database with a <datasource> variable on the imagecontrol. We are refering to database manipulation only. The Interface.openCampaignFolder() would be what is accessing the files on the harddrive (which I believe still works).

Moon Wizard
April 26th, 2017, 18:27
I'm not following what the issue is here.

Assets can only be defined during load, in order to keep the program complexity down. (i.e. frames, fonts, dice, window classes, templates, icons)
Images can be added to the images folder for the campaign or dropped on the images list, and it will automatically create image nodes. (i.e. image.id-0000#.image)
General access to load files from anywhere on the drive is deliberately disabled.

Perhaps providing an example of specifically what you are trying to build would be useful, so we can make suggestions.

Regards,
JPG

Trenloe
April 26th, 2017, 18:44
I think this thread has been going at cross purposes - with two different discussions going on. Nickademus seems to be fine with having images stored in the campaign database and accessing them there. He's not asking to be able to directly access them on the local computer file system - that's a side discussion that seems to have caused lots of confusion as to the original intent of this post.

Nickadmemus tells what he's trying to do in post #18.

Nickademus
April 26th, 2017, 19:25
Yeah, there are two different conversations here.

I have been working on something else the last few days so I haven't had the chance to work on this, but basically I have a subwindow that I wish to display an image. The image is one of the ones in the campaign folder and thus in the database but it changes based on what the GM does with the subwindow. I'm therefore creating the imagecontrol dynamically and I want to assign it a datasource. The problem is that datasources come from windows, not controls and the subwindow doesn't have a datasource since the image will change. I figure I'll need to either find a way to fool the imagecontrol into thinking the subwindow has a datasource so that the imagecontrol can find the image (so far the control keeps creating a 200x200 blank image which is probably the default on failure), or I'll have to find a way to create the subwindow dynamically with the proper datasource or find a way to change the subwindow's datasource before creating the imagecontrol.

I'll have more time probably tomorrow to hammer away at this and try things.

Nickademus
April 28th, 2017, 00:59
I got the windows and controls to recognize the part of the database where the image is. But no matter what I do, the imagecontrol always creates an image 200x200 that doesn't show. The image in this example is 300x300. Is there a blank 200x200 default image that is used when an imagecontrol can't properly get its image? I'm not sure what it is doing or how to make it grab the image from the database.
18695

Trenloe
April 28th, 2017, 01:51
I got the windows and controls to recognize the part of the database where the image is. But no matter what I do, the imagecontrol always creates an image 200x200 that doesn't show. The image in this example is 300x300. Is there a blank 200x200 default image that is used when an imagecontrol can't properly get its image? I'm not sure what it is doing or how to make it grab the image from the database.
18695
Not knowing what code you're using for that debug means I'm guessing, but your dbnode is showing as id-00002.image, it should be image.id-00002.

Nickademus
April 28th, 2017, 02:18
It's actually "image.id-00002.image.bitmap.<filename>.png". The first 'image' is in the window (first debug; getDatabaseNode). The second 'image' is the name of the imagecontrol, as is done in the reference manual. It has to be that way.

Though, the image it grabs from image.id-00002.image seems to be wrong.

Trenloe
April 28th, 2017, 03:52
You need to give us a more information - like some code you're actually using - maybe a skeleton extension or something we can play with to get it working. At the moment you're drip feeding us information and it's impossible for us to give true guidance.

Nickademus
April 28th, 2017, 09:32
The code I'm using looks nearly identical to the reference manual code Moon pointed to earlier in this thread. It would be very difficult to make a skeleton extension, but possible. But here is the code that it used here; not much to really look at.

function embedImage(dropNode)
local win = createWindowWithClass("imageryTest", "id-00002");
local ctrl = win.createControl("imagery", "image");
local w, h = ctrl.getImageSize();
Debug.console("getDatabaseNode()");
Debug.console(getDatabaseNode());
Debug.console("win.getDatabaseNode()");
Debug.console(win.getDatabaseNode());
Debug.console("win.children");
Debug.console(DB.getChildren(win.getDatabaseNode() , ""));
Debug.console("ctrl");
Debug.console(ctrl);
Debug.console("starting w");
Debug.console(w);
Debug.console("starting h");
Debug.console(h);
end
The 'imagery' template is a clone of the reference manual image template:

<template name="imagery">
<imagecontrol>
<anchored position="insidetopleft" />
<indicators availability="blank" locked="blank" loading="blank" zoom="blank" shortcuts="blank" />
<invisible />
<disabled />
</imagecontrol>
</template>

Trenloe
April 28th, 2017, 14:53
Assuming your image is stored in the campaign database at image.id-00002 ? i.e. It is a normal campaign image?

Then your createWindowWithClass("imageryTest", "id-00002"); needs to refer to image.id-00002, that is: createWindowWithClass("imageryTest", "image.id-00002");

This is what I was trying to point out before.

Just using "id-00002" for the image database reference will create a DB node at id-00002 in the XML root, because this is an absolute database node identifier. Check your campaign XML, I bet you'll see a DB node of "id-00002" right off the root.

I'm guessing you're getting confused between relative and absolute database references? See "Node Identifiers" here: https://www.fantasygrounds.com/modguide/database.xcp

Trenloe
April 28th, 2017, 15:02
Or, if you want to use a relative identifier put a period in front: createWindowWithClass("imageryTest", ".id-00002")

This will reference a db node relative to the <datasource> of the windowlist. For example, if the windowlist has <datasource>image</datasource> then using ".id-00002" (a relative identifier) would reference image.id-00002 as the absolute database identifier (which I believe is what you need).

Nickademus
April 28th, 2017, 22:17
Assuming your image is stored in the campaign database at image.id-00002 ? i.e. It is a normal campaign image?Yes it is.

Then your createWindowWithClass("imageryTest", "id-00002"); needs to refer to image.id-00002, that is: createWindowWithClass("imageryTest", "image.id-00002");

This is what I was trying to point out before.

Just using "id-00002" for the image database reference will create a DB node at id-00002 in the XML root, because this is an absolute database node identifier. Check your campaign XML, I bet you'll see a DB node of "id-00002" right off the root.This is interesting. It's not how the wiki describes (https://www.fantasygrounds.com/refdoc/windowclass.xcp) the behavior of the <datasource> of a window. According to it the datasource of a windowlist or subwindow is automatically relative.

A database identifier forming the base from which the actual data source is derived. For top level windows the identifier is relative to the root node of the database, for subwindows and windowlists it is relative to the containing control.

Or, if you want to use a relative identifier put a period in front: createWindowWithClass("imageryTest", ".id-00002")

This will reference a db node relative to the <datasource> of the windowlist. For example, if the windowlist has <datasource>image</datasource> then using ".id-00002" (a relative identifier) would reference image.id-00002 as the absolute database identifier (which I believe is what you need).
I'll try this.

EDIT: Yeah, it seems to be getting to the image now. It would seem I was misled by the description of the <datasource>...

Trenloe
April 28th, 2017, 22:33
Yes it is.This is interesting. It's not how the wiki describes (https://www.fantasygrounds.com/refdoc/windowclass.xcp) the behavior of the <datasource> of a window. According to it the datasource of a windowlist or subwindow is automatically relative.
Controls are relative to the window they are in, that's what this is referring to.

LUA coding is usually different.

Your debug commands you listed a few posts back were eluding to this.

Nickademus
April 28th, 2017, 22:48
Yeah, sometimes it feels like I'm grasping at straws using the wiki.

Trenloe
April 28th, 2017, 22:54
The command you used is here: https://www.fantasygrounds.com/refdoc/windowlist.xcp#createWindowWithClass It specifies "The data node identifier path..." - these are documented under "node identifiers" here: https://www.fantasygrounds.com/modguide/database.xcp Your debug statements were pretty much telling you that you weren't accessing the right nodes and going to a root of "id-0002" rather than "image.id-00002", as I eluded to also. Believe what they were telling you, rather than second guessing! ;)

Nickademus
April 30th, 2017, 02:38
Then your createWindowWithClass("imageryTest", "id-00002"); needs to refer to image.id-00002, that is: createWindowWithClass("imageryTest", "image.id-00002");

Changed to this and it works fine. The image is showing up where and I it's supposed to. Switch over to the local client and the same lua file code throws a console error:
createWindowWithClass: Unable to create target named node
Is there some aspect of a windowlist that doesn't allow players to do things? I didn't see any such note in the windowlist description. Too tired to fool with it more tonight...

Trenloe
April 30th, 2017, 03:19
Is there some aspect of a windowlist that doesn't allow players to do things?
More than likely the image hasn't been shared with the player, so it can't be accessed. Either share the image or make it public using code on the GM side: https://www.fantasygrounds.com/refdoc/databasenode.xcp#setPublic