Jump to content

Lua in UltraEngine?


WSI
 Share

Recommended Posts

So, because I'm a masochist... or at least just really stubborn and hate giving up on stuff... I'm going to jump back into learning Lua. I don't know what it is that's blocking it from "clicking" with me, when it's apparently such an easy thing to learn, but maybe I can figure it out if I bang my head against it enough.

That said!

Is Lua going to be supported in UltraEngine as well?

  • Like 1
Link to comment
Share on other sites

I'm on the struggle bus wrapping my head around Lua as it is. Actually, I think it's more learning to think like a programmer that's messing with me. The syntax itself isn't difficult to learn. When/how/why/where to use it is what's challenging me.

C++ would probably melt my brain entirely, though. And I kinda need my brain.

I'm much more on the creative side of things. I wanna learn Lua just so I can at least create good prototypes or proof-of-concepts. By no stretch am I trying to become an expert at programming. So, Lua will have to be enough for my needs.

Thanks for confirming Lua in UltraEngine!

  • Like 1
Link to comment
Share on other sites

 

Lua is a high level managed programming system and in a way it favors productivity, I've been trying to make a game for a long time, it's the excuse to learn to program always something new. 

For me the system that most favors me in Lua, is to simulate OOP programming (Object Oriented Programming), I do this through tables and files. What I do is to take a big problem and divide it into smaller parts. And to do this I had to start from scratch from main, and manage my own structure.  With time you develop skills, I don't really consider myself a programmer, but I think that with time I have improved somewhat, because I am no longer trying to learn how to do things, but I am already doing them. 

Translated with www.DeepL.com/Translator (free version)
image.thumb.png.dc8836c662a31a4e1df85d5fe74ea720.png
 

 

 

 

Link to comment
Share on other sites

Lua in Ultra Engine has some improvements, the biggest which is you no longer need to worry about deleting objects from memory, so you can just rely on Lua's garbage collection to manage everything.

Also, your Lua code runs in a thread separate from rendering, so you have a lot longer time for your code to execute, and it will have no impact on the framerate. This makes Lua perfectly fine for use with VR, since it does not bring the framerate down.

  • Like 2
  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

10 hours ago, Yue said:

For me the system that most favors me in Lua, is to simulate OOP programming (Object Oriented Programming), I do this through tables and files. What I do is to take a big problem and divide it into smaller parts. And to do this I had to start from scratch from main, and manage my own structure.  With time you develop skills, I don't really consider myself a programmer, but I think that with time I have improved somewhat, because I am no longer trying to learn how to do things, but I am already doing them. 

 

That's really cool.

I'm still at the point of learning Lua.. then looking at programs written with it in Leadwerks, or Love2D, etc... and proceeding to scratch my head as I try to understand what I'm reading. It's like understanding basic, level 1 Spanish, then reading a paragraph with Greek mixed in. I don't know Spanish that well, and don't know Greek at all, so I can't decipher what is what. It all becomes a confusing jumble.

I need to figure out how to bridge that gap where I don't know what I don't know. In other words, I can only look up how to do "x" in Leadwerks, if I know "x" exists in Leadwerks in the first place.  If that makes sense.

But I guess I'll just have to keep bashing my head into it 'til it gets through... somehow. I don't know why this is so complicated for me.

  • Like 1
Link to comment
Share on other sites

1 hour ago, WSI said:

That's really cool.

I'm still at the point of learning Lua.. then looking at programs written with it in Leadwerks, or Love2D, etc... and proceeding to scratch my head as I try to understand what I'm reading. It's like understanding basic, level 1 Spanish, then reading a paragraph with Greek mixed in. I don't know Spanish that well, and don't know Greek at all, so I can't decipher what is what. It all becomes a confusing jumble.

I need to figure out how to bridge that gap where I don't know what I don't know. In other words, I can only look up how to do "x" in Leadwerks, if I know "x" exists in Leadwerks in the first place.  If that makes sense.

But I guess I'll just have to keep bashing my head into it 'til it gets through... somehow. I don't know why this is so complicated for me.

 

In my case, what has worked is to completely clean the main.lua file, and start from scratch, with the documentation in hand. this is like anything in life, to learn to play music, you learn by playing an instrument, and the same thing happens, you learn to program by programming. 

So what I do is to have the main.lua file and many files represented in objects through the use of tables (classes), and then these objects communicate with each other.  The example is not to build a wall of a single block, as in prefabricated houses, but as is done here in Latin America, walls with several blocks, bricks that make up our program, if one fails it will not be necessary to knock down the entire wall. This has taken me several years to learn after trial and error. 

But I am sure that if you put your heart into it, you will learn something new and that is gratifying when we gain experience in something and make it applicable. 

 

  • Like 1

 

 

Link to comment
Share on other sites

Take small steps... Like Yue said, don't dive into the Main.lua..  create a blank project and start by rotating a box around the screen.  Once you have familiarize yourself on how to do that - then make the box change color or scale bigger etc...   before to long you will have a basic concept on how things flow.. plant that seed ! :) 

To be honest the programming language really isn't the obstacle to overcome,  be it C++, LUA, c# ... or whatever..   Leadwerks ( or any other game engine ) is going to take the same instructions regardless what coding language the instructions were sent from. Sure theres some differences between the actual languages which makes one choose one over the other but when it comes down to it - Leadwerks ( or whatever engine ) is what you need to learn.. The languages just give you a means to tell the game engine what you want done.  The real learning is in the game engines themselves.

I've been coding for 15 years solid,  I came over to Leadwerks about 9 months ago. I restarted my project 3 times, not because I didn't know how to code,  while learning the in's and out's of the game engine.  So as you can see the language is no barrier, it's getting a good understanding of what your working with, how you want it to work and best avenues to take provided by the game engine itself.. 

 

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

9 hours ago, Alienhead said:

Take small steps... Like Yue said, don't dive into the Main.lua..  create a blank project and start by rotating a box around the screen.  Once you have familiarize yourself on how to do that - then make the box change color or scale bigger etc...   before to long you will have a basic concept on how things flow.. plant that seed ! :) 

To be honest the programming language really isn't the obstacle to overcome,  be it C++, LUA, c# ... or whatever..   Leadwerks ( or any other game engine ) is going to take the same instructions regardless what coding language the instructions were sent from. Sure theres some differences between the actual languages which makes one choose one over the other but when it comes down to it - Leadwerks ( or whatever engine ) is what you need to learn.. The languages just give you a means to tell the game engine what you want done.  The real learning is in the game engines themselves.

I've been coding for 15 years solid,  I came over to Leadwerks about 9 months ago. I restarted my project 3 times, not because I didn't know how to code,  while learning the in's and out's of the game engine.  So as you can see the language is no barrier, it's getting a good understanding of what your working with, how you want it to work and best avenues to take provided by the game engine itself.. 

Now that's a very different perspective on it. My Spanish mixed with Greek analogy actually makes a lot of sense from that angle. It's not the Lua that's messing with me, it's the LW specific stuff. Interesting! So I guess I had the right idea there.

As for for not diving into Main.lua.. I was under the impression that Main.lua is required? Isn't that what's run first, regardless? I will say, looking at Lua, and all those commented out bits does feel a bit overwhelming.

Link to comment
Share on other sites

13 hours ago, Genebris said:

Have you tried just going though a list of classes and method in Leadwerks? You will see what you can do and example show you when you can use it. Try reading various methods of Entity class.

https://www.leadwerks.com/learn?page=API-Reference_Object_Entity_AddForce

I did actually try that approach to import a simple ball I modeled in Blender and make it move forward by pressing W. It wouldn't work. The ball wouldn't move. I couldn't figure out what I was doing wrong because, again, I don't know what I don't know. Looking at this monster list of things in the API reference was overwhelming and I didn't understand what I was looking at. So I got frustrated and gave up.

I can look at it again, but I think the same thing is going to keep happening.. I don't understand what I'm looking at, so all I'm doing is copying and pasting (or re-typing if I choose that route) code provided to me. It's not helping me learn, and I still won't know where/when to use it, if I don't understand what it's doing. 

This is the wall I keep hitting, and it's why "just start doing it" doesn't work for me. It's like knowing how to bake, versus following the steps on a cake box. Following the steps on the box will yield me a tasty cake in the end. But it won't teach me how to bake.

I'm genuinely impressed by how people self-teach themselves this stuff. I don't understand how they do it.

Link to comment
Share on other sites

Well  you do need a MAIN.lua, but it doesn't have to be the framework main.lua included with LE.

Here's the most basic framework you need to start a project.  It creates and spins a cube on the screen.


-- Create a window
window = Window:Create("Start", 0, 0, 800, 600, Window.Titlebar+Window.Resizable)  --<< we need a window to start


-- Create the context panel 
context=Context:Create(window) --<< we need a panel; to draw to ( panel is created inside the window )

world = World:Create()
World:SetCurrent(world)  --<< we need a world to play in. :)

-- Make a 3d cube
entity = Model:Box() --<< we need a 'thing' in the world to look at .


-- Main Loop
while true do

    -- do your 3d stuff here
    entity:Turn(0,1,0)   --<<< make the 'thing' do something.

    --Update the app timing
    Time:Update()

    --Update the world
    world:Update() ---<< update the world ( let a day pass )

    --Render the world
    world:Render()  -- << no other 3d operations will show up after rendering, until the next pass


    -- If you were doing any 2D, text or images
    -- they would go here. After Rendering but
    -- before flipping.

    context:Sync(false)   ---<<< flip everything that happebd in this loop to the display buffer.

end

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, Alienhead said:

Well  you do need a MAIN.lua, but it doesn't have to be the framework main.lua included with LE.

Here's the most basic framework you need to start a project.  It creates and spins a cube on the screen.


-- Create a window
window = Window:Create("Start", 0, 0, 800, 600, Window.Titlebar+Window.Resizable)


-- Create the context panel 
context=Context:Create(window)

world = World:Create()
World:SetCurrent(world) 

-- Make a 3d cube
entity = Model:Box()


-- Main Loop
while true do

    -- do your 3d stuff here
    entity:Turn(0,1,0)

    --Update the app timing
    Time:Update()

    --Update the world
    world:Update()

    --Render the world
    world:Render()


    -- If you were doing any 2D, text or images
    -- they would go here. After Rendering but
    -- before flipping.

    context:Sync(false)

end

Ah okay, that makes sense. So basically do what they do in the Lua tutorial. I could try that. Maybe not having that wall of green text will at least help me focus on what I need "right now".

I think I just need to figure out how translate what I'm seeing on screen into "plain English". Once I can back the code and understand it that way, I know I'm 'getting it'. Until then, it's like reading Greek.

But.. I'll keep pushing at it!

Thanks for the explanation.

  • Like 1
Link to comment
Share on other sites

15 hours ago, Alienhead said:

Well  you do need a MAIN.lua, but it doesn't have to be the framework main.lua included with LE.

Here's the most basic framework you need to start a project.  It creates and spins a cube on the screen.


-- Create a window
window = Window:Create("Start", 0, 0, 800, 600, Window.Titlebar+Window.Resizable)  --<< we need a window to start


-- Create the context panel 
context=Context:Create(window) --<< we need a panel; to draw to ( panel is created inside the window )

world = World:Create()
World:SetCurrent(world)  --<< we need a world to play in. :)

-- Make a 3d cube
entity = Model:Box() --<< we need a 'thing' in the world to look at .


-- Main Loop
while true do

    -- do your 3d stuff here
    entity:Turn(0,1,0)   --<<< make the 'thing' do something.

    --Update the app timing
    Time:Update()

    --Update the world
    world:Update() ---<< update the world ( let a day pass )

    --Render the world
    world:Render()  -- << no other 3d operations will show up after rendering, until the next pass


    -- If you were doing any 2D, text or images
    -- they would go here. After Rendering but
    -- before flipping.

    context:Sync(false)   ---<<< flip everything that happebd in this loop to the display buffer.

end

I copied this and am going to use it as my base main.lua for now.

Thank you again for typing that all out.

Link to comment
Share on other sites

-- ***********************************
-- Proyecto : Astrocuco
-- Scripter : Yue Rexie
-- Fichero  : CInput.lua
-- ***********************************
-- Notas 	: Clase CInput para 
-- 			  crear el objeto Input.
-- ***********************************


CInput={

	window = nil;

	New = function (self)
		local this={}
		setmetatable(this,self)
		self.__index = self
		
		function this:Init()
		
			self.window = Window:GetCurrent()

			System:Print(">>> ### CREANDO OBJETO INPUT... ¡OK! ### <<<")
		end

		function this:KeyHit(CodeKey)

			return (self.window:KeyHit(CodeKey))
		end

		function this:KeyDown(CodeKey) 
			return ( self.window:KeyDown(CodeKey))
		end 

		function this:FlushKeys()
			self.window:FlushKeys()
		end

		function this:MouseDown(CodeKey)
			self.window:MouseDown(CodeKey)
		end

		this:Init()
		return(this)
	end
}

 

Check out some of my object-oriented flow programming. Esto es una clase, y por lo regular la pongo en un fichero aparte. 

Ahora el siguiente paso es construir un objeto de esa clase.

 


-- File Main.lua
import("Class/CInput.lua")

input = CInput:New()

-- Sample.
if input:KeyDown(Key.F) then
  System:Print("Key F Down")
End

 

Remember from the beginning that your whole game is one big object, which must be made up of other objects. Think of it as a car, a single object that has other objects, the wheels object, the chassis object, the engine object, the steering wheel object. All these objects must communicate with each other, the pedal object when pressed accelerates the motor object and makes the car move. 

The Main file, is the input file to the program, the rest are the way to structure your code. The entities within a map can be assigned scripts, but everything internally is executed from the Leadwerks core in a Loop depending on the case or at the start of the game. 

 

 

 

  • Like 1

 

 

Link to comment
Share on other sites

On 9/7/2022 at 10:13 PM, Yue said:

-- ***********************************
-- Proyecto : Astrocuco
-- Scripter : Yue Rexie
-- Fichero  : CInput.lua
-- ***********************************
-- Notas 	: Clase CInput para 
-- 			  crear el objeto Input.
-- ***********************************


CInput={

	window = nil;

	New = function (self)
		local this={}
		setmetatable(this,self)
		self.__index = self
		
		function this:Init()
		
			self.window = Window:GetCurrent()

			System:Print(">>> ### CREANDO OBJETO INPUT... ¡OK! ### <<<")
		end

		function this:KeyHit(CodeKey)

			return (self.window:KeyHit(CodeKey))
		end

		function this:KeyDown(CodeKey) 
			return ( self.window:KeyDown(CodeKey))
		end 

		function this:FlushKeys()
			self.window:FlushKeys()
		end

		function this:MouseDown(CodeKey)
			self.window:MouseDown(CodeKey)
		end

		this:Init()
		return(this)
	end
}

Check out some of my object-oriented flow programming. Esto es una clase, y por lo regular la pongo en un fichero aparte. 

Ahora el siguiente paso es construir un objeto de esa clase.



-- File Main.lua
import("Class/CInput.lua")

input = CInput:New()

-- Sample.
if input:KeyDown(Key.F) then
  System:Print("Key F Down")
End

Remember from the beginning that your whole game is one big object, which must be made up of other objects. Think of it as a car, a single object that has other objects, the wheels object, the chassis object, the engine object, the steering wheel object. All these objects must communicate with each other, the pedal object when pressed accelerates the motor object and makes the car move. 

The Main file, is the input file to the program, the rest are the way to structure your code. The entities within a map can be assigned scripts, but everything internally is executed from the Leadwerks core in a Loop depending on the case or at the start of the game. 

I appreciate you sharing that. I have to be honest, though... I don't know what I'm looking at lol. 
I'm just trying to understand Lua and LW3D's specifics... Object oriented programming is well beyond me at this point.
I'm sure it's helpful to others who are further along though.

Link to comment
Share on other sites

 

What happens is that your game will be big as time goes by, and object oriented programming aims to break a huge program into smaller parts, the only thing I can think of and from my own experience is that it will take some time when you learn to program and understand Leadwerks.  And then if you take the step to create a game. 

What I am trying to explain is that you have two options, one is to write your entire program in a single file, this would be equivalent to writing on an Egyptian paper, this will create spaghetti code, if you write your program as a book, separated by sheets, chapters and paragraphs. Because the hardest part is when you start debugging your program and most of the bugs are just in our coders head. 

And something important, don't give up. 

Translated with www.DeepL.com/Translator (free version)

 

 

 

Link to comment
Share on other sites

 

An object is a list of attributes that represent an object to us as programmers. In the real world we have objects like a ball, it has properties like color, material, and events that are triggered for example when the ball is kicked. 

This ball can be in another much larger object, a soccer stadium, where there are objects such as the field, the players, the referee.

The idea of objects in programming, is that you work in smaller parts that are then of larger ones. Leadwerks has objects, such as the Windows object, which in turn has a context. 

So when you understand this, it is much more fun to program and you won't feel like your brain is going to explode, but you need time to assimilate these things and perceverance. 

Translated with www.DeepL.com/Translator (free version)

 

 

 

Link to comment
Share on other sites

@WSI You're probably smarter than you think. When I look at that code, I have no idea what it is doing, and it would take me a long time to walk through it and figure out what is happening. Most of the time programmers don't understand code they didn't write themselves.

Also, meta tables are some of the most obscure/advanced concepts in Lua. I'm not even sure if I use them at all.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

-- ***********************************
-- Proyecto : Astrocuco
-- Scripter : Yue Rexie
-- Fichero  : CPlayer.lua
-- ***********************************
-- Notas 	: Clase CPlayer para 
-- 			  crear el objeto Player.
-- ***********************************
import ("Scripts/Class/CCamP.lua")
import ("Scripts/Class/CMove.lua")
import ("Scripts/Class/CAnimP.lua")
import ("Scripts/Class/CHudP.lua")
import ("Scripts/Class/CItemsV.lua")
import ("Scripts/Class/CInven.lua")
import ("Scripts/Class/CRag.lua")

CPlayer={

	camera = nil;
	move   = nil;
	anim   = nil;

	hud    = nil;
	itemsV = nil;
	inven  = nil;


	rag    = nil;

	New = function (self)
		local this={}
		setmetatable(this,self)
		self.__index = self
		
		function this:Init()
		
			self.window = Window:GetCurrent()
			self.camera = CCamP:New()
			self.move   = CMove:New()
			self.anim   = CAnimP:New()

			self.hud    = CHudP:New()
			self:StartHud()
			--self.itemsV  = CItemsV:New()

			self:StartInven()
	
			self.rag = CRag:New()
			System:Print(">>> ### CREANDO OJBETO PLAYER... ¡OK! ### <<<")
		end

		function this:StartInven()
			self.inven = CInven:New()
		end

		function this:StartHud()
			self.hud    = CHudP:New()
		end


		-- Update Player.
		function this:Update()
			self.camera:Update()
			self.move:Update()
			self.anim:Update()

			self.inven:Update()

			self.rag:Update()
			
		end

		function this:DrawHud()
			self.hud:Draw()
		end
	


		this:Init()
		return(this)
	end
}

This is my workflow for a character in Leadwerks. I think my hobby is to learn things and improve my skills, maybe someday I'll make a video game.

 

 

Link to comment
Share on other sites

On 9/11/2022 at 3:21 AM, Josh said:

@WSI You're probably smarter than you think. When I look at that code, I have no idea what it is doing, and it would take me a long time to walk through it and figure out what is happening. Most of the time programmers don't understand code they didn't write themselves.

Also, meta tables are some of the most obscure/advanced concepts in Lua. I'm not even sure if I use them at all.

Hey, Josh. I really appreciate that vote confidence. If only I could convince my brain that's the case lol.

Funny thing is, I understand programming in concept. I remember hanging out with a friend (super gifted programmer) and being able to understand concepts, and even make suggestions when he was working out how to approach something... and he'd actually use them, and they worked out.

True story, I'd started to learn BASIC on my family's Vic-20 as a kid. Would sit in front of the living room TV, open the manual, type in the code in the book, then take it and apply it to my own ideas. I wanted to make a text adventure game. Wish I'd stuck with it. Could probably be a decent programmer by now if I had. Of course, being BASIC, and not interfacing with any other API, it was a lot easier to understand what was going on.

It's when I get down into it myself and start working with the syntax that my brain just goes blank, and I have no clue what's going on. That's the thing I need to get past.

That said, if you have trouble following what others' code is doing... Then maybe looking at others' code to learn isn't a good approach? It's definitely discouraging when people show me examples of code, and I don't know what I'm looking at. Because my assumption is showing me the code *should* be helpful... but it isn't. It leaves me more confused than anything.

Edited:
Anyway.. I took a personal day at work today specifically because I'm determined to sit here and work at this 'til there's some kind of breakthrough and my brain "gets it".  Yes I'm serious lol. I get weeks of personal time every year, which I'm terrible at using, so I always have way too much left by the end of the year. So... It's fine :p

Link to comment
Share on other sites

So, right off the bat, I'm hitting a wall.

I'm trying to change stuff in the code to make sure I'm understanding it. 

I looked up how Window:Create works, and I see that it accepts a number of parameters. 
Per this page: https://www.leadwerks.com/learn?page=API-Reference_Object_Window_Create

I put in the parameters based on the explanation, and it gives me an error when I try to run it.
Unfortunately, the example shown on that page doesn't actually use any of those parameters. It's just Window:Create(). So I have nothing to compare against and don't know how the parameters are supposed to be formatted. 

For example, am I supposed to actually put the "number x=0"? Or just "x=0"? (minus the quotes). I tried both ways, and both give errors.

This is what I run into every time I try to learn this engine. I follow what it shows in the documentation, and it doesn't work. Same thing happened when I tried to get a simple ball I modeled in Blender to move. Followed the documentation... didn't work. And it's been the same in every other thing I've tried.

Is the documentation not accurate? Maybe it's not me just "not getting it"? Is this stuff not noticed by others because everyone else already knows how to program and doesn't have to reference it?

How can I learn if following the documentation returns errors?

This is why I get frustrated and give up. Literally every step of the way, everything I try to do, I hit these walls. 

Link to comment
Share on other sites

1 hour ago, WSI said:

For example, am I supposed to actually put the "number x=0"? Or just "x=0"? (minus the quotes). I tried both ways, and both give errors.

Neither,  those doc examples show what the command takes as a parameter.. It's just for reference..  When actually entering the parameters for the command there is no = ( equals sign ) used.  Think of the Syntax section of the docs as a legend on map - it simply highlights what the command itself is looking for.

 

  • Window Create(string title="Leadwerks", number x=0, number y=0, number width=1024, number height=768, number style=Titlebar)

 

Would translate into 

 win = Window:Create("Leadwerks", 0, 0, 1024, 768, Window.Titlebar)

 

  • Thanks 1
Link to comment
Share on other sites

6 hours ago, Alienhead said:

Neither,  those doc examples show what the command takes as a parameter.. It's just for reference..  When actually entering the parameters for the command there is no = ( equals sign ) used.  Think of the Syntax section of the docs as a legend on map - it simply highlights what the command itself is looking for.

  • Window Create(string title="Leadwerks", number x=0, number y=0, number width=1024, number height=768, number style=Titlebar)

Would translate into 

 win = Window:Create("Leadwerks", 0, 0, 1024, 768, Window.Titlebar)

If the actual command doesn't use =, then why is it noted like that in the documentation?
That's another reason why the example code on that page should have the parameters included, to show the actual correct formatting. I could have looked at it and realized "Oh, *that's* how it's actually formatted", and everything would have worked.

So, effectively, I can't trust anything in the documentation as being accurate and will have to constantly second guess "well now... is this how it's supposed to be typed, and I'm doing it wrong? Or did they deliberately format it differently for demonstration, while providing no example of how to do it correctly?"

Someone should review the docs for accuracy and/or thoroughness. Make sure example code written is complete (includes parameters where applicable, etc), and not assume someone new will look at it and "just know" what the correct approach is.

Link to comment
Share on other sites

image.thumb.png.6ff0d2a9e9d2356be55971043c077f29.png

 

 

The first parameter is a string, a text string that is enclosed in double quotes, the example "Leadwerks" is enclosed in double quotes with the simulated equality. The X and Y parameters are set as number values, and the example is set to the numbers 0,0, where the window will be drawn in the upper left corner of the screen.  The following parameters are completely equal, for width and height. And e of the flags is to determine if the window goes to full screen mode, if it is drawn centered.  

Translated with www.DeepL.com/Translator (free version)



 

 

 

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...