LUA - Create primitives and instance objects

LUA - Create primitives and instance objects

Anonymous
Not applicable
1,102 Views
8 Replies
Message 1 of 9

LUA - Create primitives and instance objects

Anonymous
Not applicable

Dear Stingray community

 

slowly I'm starting to extend the editor functionality of Stingray and to write my own custom nodes and classes etc. the training videos by you guys have been a great help so far.
Nevertheless, I came accross the fact that I want to create geometry based on a button click. I don't want to procedurally create new meshes, I actually would like to do two things that are pretty standard in Unity for example.

1. I want to click a button from a custom plugin (already have that) and create a simple cube at a fixed position in the 3D world. What I miss here is the LUA-command for creating a primitive. I've been searching for "stingray.Primitive" or "stingray.Cube" but could not find anything.

2. I want to click a button from a custom plugin and instance an object from a sort of prefab or a resource stored somewhere as a unit (?) and place it in the world. In Unity you would need to store the "Prefab" inside of the project's resources folder or download it asychronously via an asset bundle, pass the path to the GameObject.Instance(...) method and you're done.
How would I achieve something like that in LUA for Stingray?

Best regards

Mirko

Reply
Reply
0 Likes
Accepted solutions (1)
1,103 Views
8 Replies
Replies (8)
Message 2 of 9

Shanii2
Collaborator
Collaborator

You can follow the Lua script for creating the meshes at runtime and constraint only to a part where a simple cube forms. Then you can cache your entire code to another function which you can later call dynamically to spawn at such places. You can find an example of creating custom Lua code and functions and then calling them in another function or even expose it to FLOW by creating custom flow nodes.

Reply
Reply
0 Likes
Message 3 of 9

Anonymous
Not applicable

Hei Shanii2

thanks for your answer. If I get you right, you suggest to form a cube by creating it mathematically via the dynamic mesh creator and save this code?
If that's correct this won't help me with my second part of the question, since I want to instantiate existing geometry that can not be created programmatically (or would cost at least ten times the time a modeler would need to prepare a single model). Is there any other solution, or did I got you wrong?


Best regards,


Mirko

Reply
Reply
0 Likes
Message 4 of 9

_robbs_
Alumni
Alumni

You can spawn any unit in your project by using

 

stingray.World.spawn_unit( world, "my/unit/resource_name", position, rotation )

 

So say you have some 3D geometry that you've created in 3ds Max or Maya or some other design app. You save it as an FBX and import it into your Stingray project, and it gets imported as a unit. You can then spawn as many instances of these units as you want in the level.

 

To spawn a built-in primitive like a cube or sphere, use the primitive unit resources that you'll find in the "core" resources. So, for example,

 

stingray.World.spawn_unit( world, "core/units/primitives/cube_primitive", position, rotation )

 

Reply
Reply
0 Likes
Message 5 of 9

Shanii2
Collaborator
Collaborator

hehhehe i though you wanted to create mesh procedurally.  Actually in Stingray when ever a unit is spawned its memory is allocated, and its instance is spawned is spawned in level all the other duplicates of this units inherit their properties by its parent unit stored in memory. Hence spawning large no of same unite does'nt add much to memory because they all use the reserved memory. 

If you want to create a unit by lets say mouse click on the fly. then you simply need to create a short function that would fetch the mouse screen position and translate it to world position. then simply call the function like you see above. to spawn a unit at the place. primitives are actually stored in core resources hence you need to target that resource name if you want to dynamically spawn the primitives.

 

the proceduraly mesh creation is just a new feature added to create meshes on the fly dynamicaly and applying materials.  

be sure to check that lua code too if you want to create some of your own . however the best is to use the graphic tool to create geometry or objects that you want. 

 

 

If you want something to spawn procedurally creating a structure in the scene. then off course you need small parts or sections of geometry to spawn along a specific path. like lets say a Train track, you need to just create a section in 3d graphics tool. that can be align to form a track. Then the rest is simply done programmatically in lua or flow.  If you want to spawn objects procedurally..

 

 

Reply
Reply
0 Likes
Message 6 of 9

Anonymous
Not applicable

Hei _robbs_

fantastic, thanks, it worked... almost.

What I tried as a testing purpose was this:

I've created a Stingray test.stingray_plugin file and put in those lines:

        path = "Edit/Create something"
        action =
		{
			type = "lua"
            script = """
                print("Spawning a cube")
				world = stingray.Application.main_world()
				world:spawn_unit("core/units/primitives/cube_primitive", stingray.Vector3(0,0,0), stingray.Quaternion.identity())
				print (world)
				print ("Done")
            """
        }

This creates a cube when I click the "Edit/Create something" button into my main_world (another concept I do not fully understand in Stingray but that can be left as another topic for another day).

However the cube does not show up in my "Units" folder in Stingray:

Issue.png

Is there something I need to call afterwards to add it to my units-list?

 

Best regards,

Mirko

Reply
Reply
0 Likes
Message 7 of 9

_robbs_
Alumni
Alumni
Accepted solution

Hey Mirko,

 

so that call is spawning the unit in the engine. If you want to spawn a unit at runtime in your project's Lua code -- so that it happens when you do Test Level or Run Project or deploy to an exe file -- that's all you need to do.

 

However, if you want to spawn it at edit time, there's a bit more to it. The editor maintains a ton of state information about the objects in the level, the current operations you're doing on them, what is currently selected iin the viewport, what tools you have selected, etc etc. Most of this is done through a pile of Lua code inside core/resources/editor_slave/stingray_editor. That code communicates with the editor's front-end JavaScript application through a C# backend. So, you need to do some extra calls to make the editor's front-end windows like the tree in the Explorer panel aware of the changes you're making in the running engine.

 

Here's how to update the editor on spawn:

 

 

    -- create your unit in the engine
local position = stingray.Vector3(0, 0, 0) local unit_type = "core/units/primitives/sphere_primitive" local id = Application.guid() local engine_unit = stingray.World.spawn_unit(LevelEditing.world, unit_type, position) Unit.set_id(engine_unit, id)
-- make an editor level object for it local script_data = nil -- this can hold custom script data you want to assign to your unit, if any local materials = {} editor_level_object = UnitObject(engine_unit, id, unit_type, nil, materials, script_data) Unit.trigger_unit_spawned(engine_unit)
-- register the new object with the editor LevelEditing:register_gizmo(engine_unit) LevelEditing.objects[editor_level_object.id] = editor_level_object LevelEditing:spawned({editor_level_object})

 

this'll also mark your level as dirty, so that when you save, your newly spawned unit will be there next time you open the level.

Reply
Reply
Message 8 of 9

_robbs_
Alumni
Alumni

Unfortunately it can be pretty challenging to work with that editor Lua code.  It's not cleanly exposed and documented the way the runtime Lua interfaces are.

 

You'll often need to dig through that core/editor_slave/stingray_editor folder to try to figure out how things work.

Reply
Reply
Message 9 of 9

Anonymous
Not applicable

Hei _robbs_

 

your answer is great and fully solved the problem. I was assuming that it had something to do with the update state of the world, that's why I tried out world:update() but without any luck.

I would have never found your solution or thought of calling the JS editor update methods.
This is pretty tough and I can tell already that I will probably have more questions in the future about this.
But for now, thank you very much on clearing this up. Thank you Shanii2 as well. 🙂

 

Best regards,

Mirko

Reply
Reply
0 Likes