This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Dave-ee Jones's profile picture

Windows or Objects?

Started by Dave-ee Jones, 27 February 2017 - 12:38 AM
Dave-ee Jones #1
Posted 27 February 2017 - 01:38 AM
Hey!

So I've come to the crossroads between writing a script to draw objects on a screen or just using windows and drawing things in those instead.

By drawing objects on a screen I mean drawing things like buttons with text etc. I know you can do this with windows but would that decrease performance significantly if I used multiple windows for different buttons/menus etc.?

I want to create windows that have other programs running in them as well (like creating multiple instances of shells), so that'll be happening in the background separately from the other objects or 'object windows'.

With the windows API I could draw things in the window a bit easier (and also harder because I have to create functions to calculate the actual cursor position within the active window) and I could run multiple windows doing different things 'in parallel' as well.

What do you think? Pros and cons wise I reckon sticking with objects is better and having the other windows acting as program-runners, but what are your thoughts?
KingofGamesYami #2
Posted 27 February 2017 - 02:15 AM
If you're talking about creating a new window object for every single button or element, DON'T. That's not how it should be used and there is no benefit to doing so. In fact, there are several downsides.

Now, obviously you would need a window to restrict other program's access to the screen if you're trying to do what I think you're trying to do, which is the intended use of the window API and therefore appropriate.
Dave-ee Jones #3
Posted 27 February 2017 - 05:47 AM
If you're talking about creating a new window object for every single button or element, DON'T. That's not how it should be used and there is no benefit to doing so. In fact, there are several downsides.

Now, obviously you would need a window to restrict other program's access to the screen if you're trying to do what I think you're trying to do, which is the intended use of the window API and therefore appropriate.

Yeah, I didn't think it would be wise. At the moment I just have some OOP coding that draws objects (tables of data values - x,y,w,h,colour,label etc.) which works fine. :)/>

Yes, I will be using the windows API for all that, don't you worry ;)/>
Exerro #4
Posted 27 February 2017 - 03:11 PM
If you're talking about creating a new window object for every single button or element, DON'T. That's not how it should be used and there is no benefit to doing so. In fact, there are several downsides.

Windows aren't particularly efficient at rendering, but if you have a nested structure of elements and you only draw changes, the caching can actually give you a bit of a performance gain. That being said, I've never used windows myself, just self-written buffer libraries, so they might've been more optimised for drawing in this style.

Have you considered using a GUI framework? They're generally pretty good at drawing buttons and stuff. I know Titanium handles buttons and windows.
Dave-ee Jones #5
Posted 28 February 2017 - 03:27 AM
If you're talking about creating a new window object for every single button or element, DON'T. That's not how it should be used and there is no benefit to doing so. In fact, there are several downsides.

Windows aren't particularly efficient at rendering, but if you have a nested structure of elements and you only draw changes, the caching can actually give you a bit of a performance gain. That being said, I've never used windows myself, just self-written buffer libraries, so they might've been more optimised for drawing in this style.

Have you considered using a GUI framework? They're generally pretty good at drawing buttons and stuff. I know Titanium handles buttons and windows.

Yeah my code is made to only draw changes, except every 30 seconds it buffers anyway just to refresh anything in the background (notifications or whatever). I changed it from 10 seconds because the flickering got a little annoying. :P/>

Using a GUI framework is just boring in my eyes to be honest. It's like more than half your coding is gone. No fun at all :(/>
I find it is far more interesting making your own that suits what you are designing.
Dave-ee Jones #6
Posted 28 February 2017 - 05:54 AM
Hey,

Yes, another question!

Can someone show me an example of how I would create multiple windows (that are draggable, meaning I should be able to click in other places on the screen and interact with other things on the screen - not just the windows) that can run their own programs independent of each other?

E.g. 2 separate windows each running their own shell and I can swap between them and do other stuff as well.

The windows I am thinking of can be infinite basically (store data in a table).

Thanks.
Dog #7
Posted 28 February 2017 - 06:10 AM
The best example I can think of would be Lyqyd OS
Dave-ee Jones #8
Posted 28 February 2017 - 09:04 AM
The best example I can think of would be Lyqyd OS

I KNEW SOMEONE WOULD SAY THAT! Ugh!

Everytime I try and install it it just crashes and fails to install the packages. I looked in his Github files and noticed that half the packages it wants to download don't even exist.
Bomb Bloke #9
Posted 28 February 2017 - 09:12 AM
Threads merged; please keep questions about the one project in the one place.
Dave-ee Jones #10
Posted 28 February 2017 - 09:56 AM
Threads merged; please keep questions about the one project in the one place.

Who said they are for the one project??

Are you assuming my project…? Mate. You can't assume anything in the 21st century. Quite dangerous…:P/>

In all serious, no problem :D/>
Lupus590 #11
Posted 28 February 2017 - 11:07 AM
Everytime I try and install it it just crashes and fails to install the packages.

I had no issue installing via packman (once a bug involving multishell was fixed), could you post some screenshots or something?
Edited on 28 February 2017 - 10:07 AM
Exerro #12
Posted 28 February 2017 - 09:30 PM
Can someone show me an example of how I would create multiple windows (that are draggable, meaning I should be able to click in other places on the screen and interact with other things on the screen - not just the windows) that can run their own programs independent of each other?


local dragging

local function on_mouse_down( x, y )
	for i = #windows, 1, -1 do
		if y == windows[i].y and x >= windows[i].x and x < windows[i].x + windows[i].width then
			dragging = { window = windows[i], offset = x - windows[i].x }
			return true
		end
	end
end

local function on_mouse_drag( x, y )
	dragging.window.x = x + dragging.offset
	dragging.window.y = y
end

local function mouse_event( event, button, x, y, ... )
	if event == "mouse_click" and on_mouse_down( x, y ) then
		return
	elseif event == "mouse_drag" and dragging then
		return on_mouse_drag( x, y )
	end
	for i = #windows, 1, -1 do
		if x >= windows[i].x and x < windows[i].x + windows[i].width and y > windows[i].y and y <= windows[i].y + windows[i].height then --# note, the height is of the window content, not including the title bar
			local rx, ry = x - windows[i].x + 1, y - windows[i] + 1
			resume_coroutine( co, event, button, rx, ry, ... )
		end
	end
end

Something like that should work.

Edit: uugh it took me longer to fix the forum's indentation than to write the code, what is this.
Edited on 28 February 2017 - 08:35 PM
Dave-ee Jones #13
Posted 28 February 2017 - 10:36 PM
Can someone show me an example of how I would create multiple windows (that are draggable, meaning I should be able to click in other places on the screen and interact with other things on the screen - not just the windows) that can run their own programs independent of each other?


local dragging

local function on_mouse_down( x, y )
	for i = #windows, 1, -1 do
		if y == windows[i].y and x >= windows[i].x and x < windows[i].x + windows[i].width then
			dragging = { window = windows[i], offset = x - windows[i].x }
			return true
		end
	end
end

local function on_mouse_drag( x, y )
	dragging.window.x = x + dragging.offset
	dragging.window.y = y
end

local function mouse_event( event, button, x, y, ... )
	if event == "mouse_click" and on_mouse_down( x, y ) then
		return
	elseif event == "mouse_drag" and dragging then
		return on_mouse_drag( x, y )
	end
	for i = #windows, 1, -1 do
		if x >= windows[i].x and x < windows[i].x + windows[i].width and y > windows[i].y and y <= windows[i].y + windows[i].height then --# note, the height is of the window content, not including the title bar
			local rx, ry = x - windows[i].x + 1, y - windows[i] + 1
			resume_coroutine( co, event, button, rx, ry, ... )
		end
	end
end

Something like that should work.

Edit: uugh it took me longer to fix the forum's indentation than to write the code, what is this.

Okay, I've looked through it, and I understand most of it but what I don't understand is why you randomly put

coroutine.resume(...)
there. I know it starts/resumes a coroutine but I don't know where coroutine

co
came from. Unless you mean the program I start in the window will be known as coroutine 'co'? (Example kinda thing?) In which case, where would I create it?

EDIT: What are those for loops doing as well? I didn't know those could be done in LuaJ…The -1 is putting me off…Is it just going from the #windows down to 1 in increments of 1?
Edited on 28 February 2017 - 09:40 PM
Exerro #14
Posted 01 March 2017 - 10:58 AM
-snip-

Okay, I've looked through it, and I understand most of it but what I don't understand is why you randomly put

coroutine.resume(...)
there. I know it starts/resumes a coroutine but I don't know where coroutine

co
came from. Unless you mean the program I start in the window will be known as coroutine 'co'? (Example kinda thing?) In which case, where would I create it?

You'd have to work out what 'co' was yourself. I figured this'd be utilising coroutines to run programs, so you'll probably have some way of linking windows to their respective coroutines.

To clarify, CC passes events into coroutines via coroutine.resume(). When the shell runs, it is actually running inside a coroutine. `os.pullEventRaw()` actually calls `coroutine.yield()`, which gets data from whatever calls `coroutine.resume()` on the computer's coroutine.

I also forgot to mention that you'd want to redirect to the coroutine's window before resuming it, then redirect back afterwards.

EDIT: What are those for loops doing as well? I didn't know those could be done in LuaJ…The -1 is putting me off…Is it just going from the #windows down to 1 in increments of 1?

Yep, that's it.

for <name> = <initial>, <final> [, <increment>] do <block> end
--# increment defaults to 1
Bomb Bloke #15
Posted 01 March 2017 - 09:41 PM
Edit: uugh it took me longer to fix the forum's indentation than to write the code, what is this.

Just turn off the rich text editor and dump your code in. If the indentation appears to break before you hit Post, ignore it; it'll be fine in the finished product.
Lyqyd #16
Posted 01 March 2017 - 11:02 PM
The best example I can think of would be Lyqyd OS
I KNEW SOMEONE WOULD SAY THAT! Ugh!
Everytime I try and install it it just crashes and fails to install the packages. I looked in his Github files and noticed that half the packages it wants to download don't even exist.

All of the packages exist, and it should install just fine. If you really are having issues installing the software, please post a report with screenshots or exact error messages in the LyqydOS thread or open an issue on Github. Otherwise, I'll have to assume that the root cause is an unwillingness to attempt the installation.
Dave-ee Jones #17
Posted 02 March 2017 - 12:39 AM
The best example I can think of would be Lyqyd OS
I KNEW SOMEONE WOULD SAY THAT! Ugh!
Everytime I try and install it it just crashes and fails to install the packages. I looked in his Github files and noticed that half the packages it wants to download don't even exist.

All of the packages exist, and it should install just fine. If you really are having issues installing the software, please post a report with screenshots or exact error messages in the LyqydOS thread or open an issue on Github. Otherwise, I'll have to assume that the root cause is an unwillingness to attempt the installation.

This guy. What's the deal bro?

I found out what the problem was with that installation (I believe). It must have been a past installer you had because when I installed the pastebin installer it was trying to find a GitHub folder that wasn't there. Someone else had already posted on your forum about this issue and you must have fixed it in a later update as I managed to successfully install it last night.
Dave-ee Jones #18
Posted 02 March 2017 - 06:30 AM
Update:

I have everything working (except dragging, but I have an idea of how I will do that). It took many hours of trying to figure out what my tables were doing (getting lots of nil errors while playing around with 'for k,v in pairs() do' etc. but it all seems fine now. I can swap between objects and coroutines pretty smoothly (and run multiple coroutines at once while interacting with an object).

If you would like to test it out and even do some more debugging/suggestions feel free to use the pastebin link up top (or right here). It's FAIRLY easy to read, but isn't commented (I like it neat. Easier to read and understand. Unlike LyqydOS files anyway :P/> - Sorry Lyqyd, but it's pretty chock-a-block :mellow:/>)

Thanks for all the suggestions/support/feedback/constructive criticism :D/>