Forum

User posts Charlie
18 July 2017 20:21
Hi Guys,

I've been using the 'cartoon interior', to help build my project, although I'm finding it quite difficult to extrapolate some simple features, from what is quite a complex set of code.

My app works like this.

Scene objects all have a JS callback on them. The JS callback uses a custom script in the .JS, to display menus that are relevant to the object clicked.

Something like this:

function switch_cb(in_params, out_params) {
  
       document.getElementById("cssmenu").style.display='none';
       document.getElementById("cssmenu2").style.display='block';

     }


With me so far?

The challenge after pulling in the correct menu, is to have the object and it's material 'selected' globally, so I can use the HTML menu to affect it's appearance (by applying mat's and textures).

The cartoon interior does a pretty good job of getting me started, especially with the delete and rotate functions… I'm just not there yet.

So far, I've used a separate (to the JS callback custom script - I want to use that simply for menu allocation) 'pick object' script, and that works great:

function main_canvas_down(e) {
   
    if (_disable_interaction)
        return;

    if (e.preventDefault)
        e.preventDefault();

    var x = m_mouse.get_coords_x(e);
    var y = m_mouse.get_coords_y(e);

    var obj = m_scenes.pick_object(x, y);
    
    
    if (obj)
    console.log(m_scenes.get_object_name(obj));
	console.log(material.get_materials_names(obj));
    }   


My console reports are just in there, because at some point in the future, I'll be using the inherit material function… I have no idea how to append those variables yet, but I'll deal with that when I get to it.

The problem I have now, is getting my menu to affect the SELECTED object.

I've used this technique to successfully get the menu to affect the scene:

CSSMenu has a <span> id "action1"

<li class='has-sub'><a href='#'><span id="action1">FUNCTION LINK</span></a>


And the function is appended to it (just like in cartoon_scene) like this

function init_controls() {

    document.getElementById("action1").addEventListener("click", function(e) {
       m_data.load(APP_ASSETS_PATH + "my_project_Tex2.json", null, null, true);
});


I'm not really interested in importing an object, I was just testing the function and it works fine.

Things start to get tricky if I try to have my menu execute a function on an object that is selected, and I don't really understand how it's been achieved in cartoon_scene.

Something like this (which doesn't work)

function init_controls() {

     
      document.getElementById("action1").addEventListener("click", function(e) {
        if (obj) {
            console.log("Object is affected");
           var id = m_scenes.get_object_data_id(obj);
           m_data.unload(id);
            obj = null;
        }
    }); 


I've tried messing around with the scope, by declaring obj as a global, and various other iterations that a noob might try, but I'm having no success.

The cartoon interior uses a more complex structure, but I don't understand it… It has a top level function (init_controls), then those functions are mapped to the scene somehow, like this:

function init_buttons() {
    var ids = ["delete", "rot-ccw", "rot-cw"];

    for (var i = 0; i < ids.length; i++) {
        var id = ids[i];

        document.getElementById(id).addEventListener("mousedown", function(e) {
            var parent = e.target.parentNode;
            parent.classList.add("active");
        });
        document.getElementById(id).addEventListener("mouseup", function(e) {
            var parent = e.target.parentNode;
            parent.classList.remove("active");
        });
        document.getElementById(id).addEventListener("touchstart", function(e) {
            var parent = e.target.parentNode;
            parent.classList.add("active");
        });
        document.getElementById(id).addEventListener("touchend", function(e) {
            var parent = e.target.parentNode;
            parent.classList.remove("active");
        });
    }
}


This is where I'm out of my depth. I simply want to be able to (at this stage) delete an object, that's selected, using my HTML, but I'm stuck. Any pointers???

Thanks in advance
18 July 2017 19:59
Thanks Ivan. That's not an issue though, as I'm assigning the material to 'the target' first, in the selection process.

Thanks guys
15 July 2017 02:21
Hi, hope you're all well.

I'll try to cut the waffle and stay specific.

My app uses two iFrames (see here): link

The Yellow area, represents the top level 'index.html'

'1' represents an iFrame that shows conditional menus (depending on what scene object is clicked)
'2' represents an iFrame that shows 'my_project.html' (contains the main canvas div and all JS dependencies)

I can get my scene to 'talk' to iFrame 1, using something like:
 function swap_cb(in_params, out_params) {
            
        var loc = "Menu2.html";
        parent.document.getElementById('myFrame').setAttribute('src', loc);
        
    }


As you can see, I'm using a JS Callback node to execute the code. In time, I'll swap this to OBJECT_IS_SELECTED with onClick, but for now I want to keep things slightly more simple.

The thing is, I'm struggling to have my menu (contained WITHIN 'iFrame' one, to execute code in my scene)

An important thing to note: I've looked very closely at cartoon_interior and it would be great if I only had one app, and the menu never changed. But due to the fact I'm trying to build something that's scaleable, with multiple conditional menus, it's not quite right for what I want. - I'd like to execute the code from the menu, not from within the my_project.js This is where I get stuck with 'scope'.

So, put simply, as an example scenario…

How would I get my menu (which has it's own dependent JS, for slide animations etc) and is currently unassociated with my_project.js to execute something like this in my scene:

function import_texture() {
        if (_selected_obj) {
            var id = m_scenes.get_object_data_id(_selected_obj);
            m_tex.change_image(_selected_obj, "My_Texture", "./test.png");      
        }


Challenging for someone with a small brain like me :-(
14 July 2017 22:07
Thanks Will, thanks Ivan.

So, Will, what you're saying is, technically I have to import the secondary object before I can inherit a material from it. I can't just reference the object and inherit/import it's texture to my target mesh?

This isn't a big deal, as I'm building a room configurator and there's only so many core materials I'm ever likely to use; 'Surface Glossy', 'Surface Matte', 'Semi Reflective', 'Fully Reflective', 'Metallic' and 'fabric'. I don't even think I'll need complex materials with normal maps, as I'm shooting for performance over photo-realism.

I could just have 5 or 10 spheres behind the camera.

So, Ivan, 'Replacing Textures' is probably the only external reference I'll need.

Here's how my UI structure is going to work.

I'm using a multi level menu (one menu heading for each core material) for a two step selection process.

You click an object on screen, and using an 'object_is_selected' method, the corresponding menu appears in an Iframe.

So let's say the object is 'the floor' and is selected. - A pertinent menu appears in the iFrame, with top level selections; 'Carpet', 'Wood', 'Ceramic' and 'Vinyl'. When one is selected the selected object inherits the correct material.

The second level of the menu (a drop-down or similar) shows the different 'woods', 'carpet patterns' etc. These are only textures and I intend to use the 'change texture method' with an external file structure (I hope to eventually plug this into a CMS).

So, providing that all of my textures are seamless and the target objects are UV un-wrapped and their scale is believable (and they're based on the same 'standard' as the ones contained within the 'donor material'), I should be able to simply flip from texture-to-texture within the 'selected object' without affecting the material that it was inherited from right?

C
14 July 2017 00:34
Yes! I've started using your advice as standard. Basically creating a project in Project Manager the second the default cube appears, and then putting all of my assets in place, before I do anything. It's a much 'tidier' way of working.

I've made huge leaps and bounds today, I'm just trying to figure out best practice for 'nesting' functions (I think you mentioned this pretty early on in our dialogue). At the moment, I'm trying to inherit a material from another blend… I've posted this in 'programming'.

Thanks so much for you're help, I would've given up a week ago if you weren't around.

C
13 July 2017 22:58
Hi Everyone,

Having a much better day today with B4W. Starting to get the hang of it.

Hopefully this should be a simple answer for someone, as I'm getting a bit smarter and know how to ask the questions more efficiently.

I'm trying to inherit a material from one blend file to my primary app blend file.

Steps I've taken so far:

Made 2 projects (the primary ((tex 1)) with a JS callback node) and the secondary ((tex2)) with nothing more than a cube and material.

I've saved the blend file and JSON file from 'tex2' along with moving the material texture in the 'tex1' project directory.

I've included 'obj', 'mat', 'scenes' and 'logic nodes' into my require list.

…Appended my function to a custom call back and written the following code (I'm taking baby steps remember)

m_data.load(APP_ASSETS_PATH + "my_project_Tex2.json");


This doesn't do anything unpredictable, it simply imports the cube from the my secondary blend file to my primary. Which is a good start… NO CONSOLE ERRORS YEEHAR!

But obviously I'm wanting to only import the material from the cube in 'tex2'.

So how do I amalgamate my 'secondary APP_ASSETS_PATH' with:

var cube1 = m_scenes.get_object_by_name("Cube1");
var cube2 = m_scenes.get_object_by_name("Cube2");
m_mat.inherit_material(cube1, "MyMaterial_1", cube2, "MyMaterial_2");


Thanks in advance
13 July 2017 06:31
I tried automatically packing it as external data as you suggested. This works! However, it's a little bit of a concern as my project will consist of dynamically loading materials (which will contain textures), with the whole idea being to keep the 'active' blend files as light as possible whilst using inherit_material with an external library (blend file)

It's only confusing because B4W hasn't always done this, it's a really recent occurrence. I made this link after using B4W for just 2 days, and I knew ABSOLUTELY nothing about it, and I'm pretty sure I didn't build, put my textures in assets and THEN apply them. I think I should get some sleep and come back to it.

As always, thanks for your help. If you're not an employed Ambassador for B4W, you probably should be :-)
13 July 2017 06:01
I think I've solved it.

You may remember yesterday that my Node Trees weren't saving. A big problem for executing my JS callback.

I used the 'welsh guys' file as a start file as his didn't have the problem, and there is probably file dependencies in the hierarchy that lead to his local machine, which may be confusing Blender.

I'll come back to this in the morning.

G'night and thanks.
13 July 2017 05:51
Let me know if you spot anything:

link

Thanks again
13 July 2017 05:39
Yes there's an error: "Could not load image", it's a PNG and I've used the image before, lots of times.

I reloaded, and still no joy. I might make a small video fir this one.

C