Przeglądaj źródła

Merge branch 'master' of github.com:taylor001/crown

Daniele Bartolini 9 lat temu
rodzic
commit
0fd8d202c2

+ 38 - 35
docs/lua_api.rst

@@ -612,69 +612,72 @@ Sprite
 ------
 
 **sprite_create** (rw, unit, sprite_resource, material_resource, visible, pose) : Id
-	Creates a new sprite instance for *unit* and returns its id.
+	Creates a new sprite instance for the *unit* and returns its id.
 
-**sprite_destroy** (rw, id)
-	Destroys the sprite *id*.
+**sprite_destroy** (rw, unit)
+	Destroys the sprite of the *unit*.
 
-**sprite_set_frame** (rw, id, index)
-	Sets the frame *index* of the sprite *id*.
+**sprite_instances** (rw, unit) : Id
+	Returns the IDs for all the sprites of the *unit*.
 
-**sprite_set_visible** (rw, id, visible)
-	Sets whether the sprite *id* is *visible*.
+**sprite_set_frame** (rw, unit, index)
+	Sets the frame *index* of the sprite.
 
-**sprite_flip_x** (rw, id, flip)
+**sprite_set_visible** (rw, unit, visible)
+	Sets whether the sprite is *visible*.
+
+**sprite_flip_x** (rw, unit, flip)
 	Sets whether to flip the sprite on the x-axis.
 
-**sprite_flip_y** (rw, id, flip)
+**sprite_flip_y** (rw, unit, flip)
 	Sets whether to flip the sprite on the y-axis.
 
-**sprite_instances** (rw, unit) : Id
-	Returns the IDs for all the sprites of the *unit*.
-
 Light
 -----
 
 **light_create** (rw, unit, type, range, intensity, spot_angle, color, pose) : Id
-	Creates a new light for *unit* and returns its id.
+	Creates a new light for the *unit* and returns its id.
 	Type can be either `directional`, `omni` or `spot`.
 
-**light_destroy** (rw, id)
-	Destroys the light *id*.
+**light_destroy** (rw, unit)
+	Destroys the light of the *unit*.
 
 **light_instances** (rw, unit) : Id
 	Returns the IDs for all the lights of the *unit*.
 
-**light_type** (rw, id) : string
-	Returns the type of the light *id*.
+**light_type** (rw, unit) : string
+	Returns the type of the light of the *unit*.
 	It can be either `directional`, `omni` or `spot`.
 
-**light_color** (rw, id) : Color4
-	Returns the color of the light *id*.
+**light_color** (rw, unit) : Color4
+	Returns the color of the light.
+
+**light_range** (rw, unit) : float
+	Returns the range of the light.
 
-**light_range** (rw, id) : float
-	Returns the range of the light *id*.
+**light_intensity** (rw, unit) : float
+	Returns the intensity of the light.
 
-**light_intensity** (rw, id) : float
-	Returns the intensity of the light *id*.
+**light_spot_angle** (rw, unit) : float
+	Returns the spot angle of the light.
 
-**light_spot_angle** (rw, id) : float
-	Returns the spot angle of the light *id*.
+**light_set_type** (rw, unit, type)
+	Sets the *type* of the light.
 
-**light_set_type** (rw, id, type)
-	Sets the *type* of the light *id*.
+**light_set_color** (rw, unit, color)
+	Sets the *color* of the light.
 
-**light_set_color** (rw, id, color)
-	Sets the *color* of the light *id*.
+**light_set_range** (rw, unit, range)
+	Sets the *range* of the light.
 
-**light_set_range** (rw, id, range)
-	Sets the *range* of the light *id*.
+**light_set_intensity** (rw, unit, intensity)
+	Sets the *intensity* of the light.
 
-**light_set_intensity** (rw, id, intensity)
-	Sets the *intensity* of the light *id*.
+**light_set_spot_angle** (rw, unit, angle)v
+	Sets the spot *angle* of the light.
 
-**light_set_spot_angle** (rw, id, angle)
-	Sets the spot *angle* of the light *id*.
+**light_debug_draw** (rw, unit, debug_line)
+	Fills *debug_line* with debug lines from the light.
 
 PhysicsWorld
 =============

+ 2 - 2
samples/core/editors/level_editor/level_editor.lua

@@ -317,7 +317,7 @@ function UnitBox:raycast(pos, dir)
 
 	local sprite_component = RenderWorld.sprite_instances(rw, self._unit_id)
 	if sprite_component then
-		return RenderWorld.sprite_raycast(rw, sprite_component, pos, dir)
+		return RenderWorld.sprite_raycast(rw, self._unit_id, pos, dir)
 	end
 
 	return -1.0
@@ -328,7 +328,7 @@ function UnitBox:draw()
 		-- Draw lights
 		local lights = RenderWorld.light_instances(LevelEditor._rw, self._unit_id)
 		if lights ~= nil then
-			RenderWorld.light_debug_draw(LevelEditor._rw, lights, LevelEditor._lines)
+			RenderWorld.light_debug_draw(LevelEditor._rw, self._unit_id, LevelEditor._lines)
 		end
 
 		local mesh_component = RenderWorld.mesh_instances(LevelEditor._rw, self._unit_id)

+ 296 - 0
src/core/network/socket.cpp

@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2012-2017 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+#include "ip_address.h"
+#include "socket.h"
+
+#if CROWN_PLATFORM_POSIX
+	#include <errno.h>
+	#include <fcntl.h>      // fcntl
+	#include <netinet/in.h> // htons, htonl, ...
+	#include <sys/socket.h>
+	#include <unistd.h>     // close
+	#define INVALID_SOCKET (-1)
+	#define SOCKET_ERROR (-1)
+	#define closesocket close
+#elif CROWN_PLATFORM_WINDOWS
+	#include <winsock2.h>
+	#pragma comment(lib, "Ws2_32.lib")
+	#ifndef _INC_ERRNO
+		#define EADDRINUSE WSAEADDRINUSE
+		#define ECONNREFUSED WSAECONNREFUSED
+		#define ETIMEDOUT WSAETIMEDOUT
+		#define EWOULDBLOCK WSAEWOULDBLOCK
+	#endif // _INC_ERRNO
+#endif
+
+namespace crown
+{
+namespace
+{
+	inline int last_error()
+	{
+#ifdef CROWN_PLATFORM_LINUX
+		return errno;
+#elif CROWN_PLATFORM_WINDOWS
+		return WSAGetLastError();
+#endif
+	}
+}
+
+namespace socket_internal
+{
+	void open(SOCKET socket)
+	{
+		socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+		CE_ASSERT(socket >= 0, "socket: last_error() = %d", last_error());
+	}
+
+	AcceptResult accept(SOCKET socket, TCPSocket& c)
+	{
+		SOCKET err = ::accept(socket, NULL, NULL);
+
+		AcceptResult ar;
+		ar.error = AcceptResult::SUCCESS;
+
+		if (err == INVALID_SOCKET)
+		{
+			if (last_error() == EWOULDBLOCK)
+				ar.error = AcceptResult::NO_CONNECTION;
+			else
+				ar.error = AcceptResult::UNKNOWN;
+		}
+		else
+		{
+			c._socket = err;
+		}
+
+		return ar;
+	}
+
+	ReadResult read(SOCKET socket, void* data, u32 size)
+	{
+		ReadResult rr;
+		rr.error = ReadResult::SUCCESS;
+		rr.bytes_read = 0;
+
+		u32 to_read = size;
+
+		while (to_read > 0)
+		{
+			int bytes_read = ::recv(socket
+				, (char*)data + rr.bytes_read
+				, to_read
+				, 0
+				);
+
+			if (bytes_read == SOCKET_ERROR)
+			{
+				if (last_error() == EWOULDBLOCK)
+					rr.error = ReadResult::WOULDBLOCK;
+				else if (last_error() == ETIMEDOUT)
+					rr.error = ReadResult::TIMEOUT;
+				else
+					rr.error = ReadResult::UNKNOWN;
+				return rr;
+			}
+			else if (bytes_read == 0)
+			{
+				rr.error = ReadResult::REMOTE_CLOSED;
+				return rr;
+			}
+
+			to_read -= bytes_read;
+			rr.bytes_read += bytes_read;
+		}
+
+		return rr;
+	}
+
+	WriteResult write(SOCKET socket, const void* data, u32 size)
+	{
+		WriteResult wr;
+		wr.error = WriteResult::SUCCESS;
+		wr.bytes_wrote = 0;
+
+		u32 to_write = size;
+
+		while (to_write > 0)
+		{
+			int bytes_wrote = ::send(socket
+				, (char*)data + wr.bytes_wrote
+				, to_write
+				, 0
+				);
+
+			if (bytes_wrote == SOCKET_ERROR)
+			{
+				if (last_error() == EWOULDBLOCK)
+					wr.error = WriteResult::WOULDBLOCK;
+				else if (last_error() == ETIMEDOUT)
+					wr.error = WriteResult::TIMEOUT;
+				else
+					wr.error = WriteResult::UNKNOWN;
+				return wr;
+			}
+			else if (bytes_wrote == 0)
+			{
+				wr.error = WriteResult::REMOTE_CLOSED;
+				return wr;
+			}
+
+			to_write -= bytes_wrote;
+			wr.bytes_wrote += bytes_wrote;
+		}
+		return wr;
+	}
+
+} // namespace socket_internal
+
+TCPSocket::TCPSocket()
+	: _socket(INVALID_SOCKET)
+{
+}
+
+void TCPSocket::close()
+{
+	if (_socket != INVALID_SOCKET)
+	{
+		::closesocket(_socket);
+		_socket = INVALID_SOCKET;
+	}
+}
+
+ConnectResult TCPSocket::connect(const IPAddress& ip, u16 port)
+{
+	close();
+	socket_internal::open(_socket);
+
+	sockaddr_in addr_in;
+	addr_in.sin_family = AF_INET;
+	addr_in.sin_addr.s_addr = htonl(ip.address());
+	addr_in.sin_port = htons(port);
+
+	int err = ::connect(_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
+
+	ConnectResult cr;
+	cr.error = ConnectResult::SUCCESS;
+
+	if (err == SOCKET_ERROR)
+	{
+		if (last_error() == ECONNREFUSED)
+			cr.error = ConnectResult::REFUSED;
+		else if (last_error() == ETIMEDOUT)
+			cr.error = ConnectResult::TIMEOUT;
+		else
+			cr.error = ConnectResult::UNKNOWN;
+	}
+
+	return cr;
+}
+
+BindResult TCPSocket::bind(u16 port)
+{
+	close();
+	socket_internal::open(_socket);
+	set_reuse_address(true);
+
+	sockaddr_in address;
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = htonl(INADDR_ANY);
+	address.sin_port = htons(port);
+
+	int err = ::bind(_socket, (const sockaddr*)&address, sizeof(sockaddr_in));
+
+	BindResult br;
+	br.error = BindResult::SUCCESS;
+
+	if (err == SOCKET_ERROR)
+	{
+		if (last_error() == EADDRINUSE)
+			br.error = BindResult::ADDRESS_IN_USE;
+		else
+			br.error = BindResult::UNKNOWN;
+	}
+
+	return br;
+}
+
+void TCPSocket::listen(u32 max)
+{
+	int err = ::listen(_socket, max);
+	CE_ASSERT(err == 0, "listen: last_error() = %d", last_error());
+	CE_UNUSED(err);
+}
+
+AcceptResult TCPSocket::accept(TCPSocket& c)
+{
+	set_blocking(true);
+	return socket_internal::accept(_socket, c);
+}
+
+AcceptResult TCPSocket::accept_nonblock(TCPSocket& c)
+{
+	set_blocking(false);
+	return socket_internal::accept(_socket, c);
+}
+
+ReadResult TCPSocket::read(void* data, u32 size)
+{
+	set_blocking(true);
+	return socket_internal::read(_socket, data, size);
+}
+
+ReadResult TCPSocket::read_nonblock(void* data, u32 size)
+{
+	set_blocking(false);
+	return socket_internal::read(_socket, data, size);
+}
+
+WriteResult TCPSocket::write(const void* data, u32 size)
+{
+	set_blocking(true);
+	return socket_internal::write(_socket, data, size);
+}
+
+WriteResult TCPSocket::write_nonblock(const void* data, u32 size)
+{
+	set_blocking(false);
+	return socket_internal::write(_socket, data, size);
+}
+
+void TCPSocket::set_blocking(bool blocking)
+{
+#if CROWN_PLATFORM_POSIX
+	int flags = fcntl(_socket, F_GETFL, 0);
+	fcntl(_socket, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : O_NONBLOCK);
+#elif CROWN_PLATFORM_WINDOWS
+	u_long non_blocking = blocking ? 0 : 1;
+	ioctlsocket(_socket, FIONBIO, &non_blocking);
+#endif
+}
+
+void TCPSocket::set_reuse_address(bool reuse)
+{
+	int optval = (int)reuse;
+	int err = setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&optval, sizeof(optval));
+	CE_ASSERT(err == 0, "setsockopt: last_error() = %d", last_error());
+	CE_UNUSED(err);
+}
+
+void TCPSocket::set_timeout(u32 seconds)
+{
+	struct timeval timeout;
+	timeout.tv_sec = seconds;
+	timeout.tv_usec = 0;
+
+	int err = setsockopt(_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
+	CE_ASSERT(err == 0, "setsockopt: last_error(): %d", last_error());
+	err = setsockopt(_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
+	CE_ASSERT(err == 0, "setsockopt: last_error(): %d", last_error());
+	CE_UNUSED(err);
+}
+
+} // namespace crown

+ 16 - 262
src/core/network/socket.h

@@ -6,45 +6,19 @@
 #pragma once
 
 #include "error.h"
-#include "ip_address.h"
+#include "network_types.h"
 #include "platform.h"
 #include "types.h"
 
 #if CROWN_PLATFORM_POSIX
-	#include <errno.h>
-	#include <fcntl.h>      // fcntl
-	#include <netinet/in.h> // htons, htonl, ...
-	#include <sys/socket.h>
-	#include <unistd.h>     // close
 	typedef int SOCKET;
-	#define INVALID_SOCKET (-1)
-	#define SOCKET_ERROR (-1)
-	#define closesocket close
 #elif CROWN_PLATFORM_WINDOWS
 	#include <winsock2.h>
 	#pragma comment(lib, "Ws2_32.lib")
-	#ifndef _INC_ERRNO
-		#define EADDRINUSE WSAEADDRINUSE
-		#define ECONNREFUSED WSAECONNREFUSED
-		#define ETIMEDOUT WSAETIMEDOUT
-		#define EWOULDBLOCK WSAEWOULDBLOCK
-	#endif // _INC_ERRNO
 #endif
 
 namespace crown
 {
-namespace
-{
-	inline int last_error()
-	{
-#ifdef CROWN_PLATFORM_LINUX
-		return errno;
-#elif CROWN_PLATFORM_WINDOWS
-		return WSAGetLastError();
-#endif
-	}
-}
-
 struct ConnectResult
 {
 	enum
@@ -109,266 +83,46 @@ struct TCPSocket
 {
 	SOCKET _socket;
 
-	TCPSocket()
-		: _socket(INVALID_SOCKET)
-	{
-	}
-
-	void open()
-	{
-		_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-		CE_ASSERT(_socket >= 0, "socket: last_error() = %d", last_error());
-	}
+	TCPSocket();
 
-	void close()
-	{
-		if (_socket != INVALID_SOCKET)
-		{
-			::closesocket(_socket);
-			_socket = INVALID_SOCKET;
-		}
-	}
+	/// Closes the socket.
+	void close();
 
 	/// Connects to the @a ip address and @a port and returns the result.
-	ConnectResult connect(const IPAddress& ip, u16 port)
-	{
-		close();
-		open();
-
-		sockaddr_in addr_in;
-		addr_in.sin_family = AF_INET;
-		addr_in.sin_addr.s_addr = htonl(ip.address());
-		addr_in.sin_port = htons(port);
-
-		int err = ::connect(_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
-
-		ConnectResult cr;
-		cr.error = ConnectResult::SUCCESS;
-
-		if (err == SOCKET_ERROR)
-		{
-			if (last_error() == ECONNREFUSED)
-				cr.error = ConnectResult::REFUSED;
-			else if (last_error() == ETIMEDOUT)
-				cr.error = ConnectResult::TIMEOUT;
-			else
-				cr.error = ConnectResult::UNKNOWN;
-		}
-
-		return cr;
-	}
+	ConnectResult connect(const IPAddress& ip, u16 port);
 
 	/// Binds the socket to @a port and returns the result.
-	BindResult bind(u16 port)
-	{
-		close();
-		open();
-		set_reuse_address(true);
-
-		sockaddr_in address;
-		address.sin_family = AF_INET;
-		address.sin_addr.s_addr = htonl(INADDR_ANY);
-		address.sin_port = htons(port);
-
-		int err = ::bind(_socket, (const sockaddr*)&address, sizeof(sockaddr_in));
-
-		BindResult br;
-		br.error = BindResult::SUCCESS;
-
-		if (err == SOCKET_ERROR)
-		{
-			if (last_error() == EADDRINUSE)
-				br.error = BindResult::ADDRESS_IN_USE;
-			else
-				br.error = BindResult::UNKNOWN;
-		}
-
-		return br;
-	}
+	BindResult bind(u16 port);
 
 	/// Listens for @a max socket connections.
-	void listen(u32 max)
-	{
-		int err = ::listen(_socket, max);
-		CE_ASSERT(err == 0, "listen: last_error() = %d", last_error());
-		CE_UNUSED(err);
-	}
-
-	AcceptResult accept_internal(TCPSocket& c)
-	{
-		SOCKET err = ::accept(_socket, NULL, NULL);
-
-		AcceptResult ar;
-		ar.error = AcceptResult::SUCCESS;
-
-		if (err == INVALID_SOCKET)
-		{
-			if (last_error() == EWOULDBLOCK)
-				ar.error = AcceptResult::NO_CONNECTION;
-			else
-				ar.error = AcceptResult::UNKNOWN;
-		}
-		else
-		{
-			c._socket = err;
-		}
-
-		return ar;
-	}
+	void listen(u32 max);
 
 	/// Accepts a new connection @a c.
-	AcceptResult accept_nonblock(TCPSocket& c)
-	{
-		set_blocking(false);
-		return accept_internal(c);
-	}
+	AcceptResult accept(TCPSocket& c);
 
 	/// Accepts a new connection @a c.
-	AcceptResult accept(TCPSocket& c)
-	{
-		set_blocking(true);
-		return accept_internal(c);
-	}
-
-	ReadResult read_internal(void* data, u32 size)
-	{
-		ReadResult rr;
-		rr.error = ReadResult::SUCCESS;
-		rr.bytes_read = 0;
-
-		u32 to_read = size;
-
-		while (to_read > 0)
-		{
-			int bytes_read = ::recv(_socket
-				, (char*)data + rr.bytes_read
-				, to_read
-				, 0
-				);
-
-			if (bytes_read == SOCKET_ERROR)
-			{
-				if (last_error() == EWOULDBLOCK)
-					rr.error = ReadResult::WOULDBLOCK;
-				else if (last_error() == ETIMEDOUT)
-					rr.error = ReadResult::TIMEOUT;
-				else
-					rr.error = ReadResult::UNKNOWN;
-				return rr;
-			}
-			else if (bytes_read == 0)
-			{
-				rr.error = ReadResult::REMOTE_CLOSED;
-				return rr;
-			}
-
-			to_read -= bytes_read;
-			rr.bytes_read += bytes_read;
-		}
-
-		return rr;
-	}
+	AcceptResult accept_nonblock(TCPSocket& c);
 
 	/// Reads @a size bytes and returns the result.
-	ReadResult read_nonblock(void* data, u32 size)
-	{
-		set_blocking(false);
-		return read_internal(data, size);
-	}
+	ReadResult read(void* data, u32 size);
 
 	/// Reads @a size bytes and returns the result.
-	ReadResult read(void* data, u32 size)
-	{
-		set_blocking(true);
-		return read_internal(data, size);
-	}
-
-	WriteResult write_internal(const void* data, u32 size)
-	{
-		WriteResult wr;
-		wr.error = WriteResult::SUCCESS;
-		wr.bytes_wrote = 0;
-
-		u32 to_write = size;
-
-		while (to_write > 0)
-		{
-			int bytes_wrote = ::send(_socket
-				, (char*)data + wr.bytes_wrote
-				, to_write
-				, 0
-				);
-
-			if (bytes_wrote == SOCKET_ERROR)
-			{
-				if (last_error() == EWOULDBLOCK)
-					wr.error = WriteResult::WOULDBLOCK;
-				else if (last_error() == ETIMEDOUT)
-					wr.error = WriteResult::TIMEOUT;
-				else
-					wr.error = WriteResult::UNKNOWN;
-				return wr;
-			}
-			else if (bytes_wrote == 0)
-			{
-				wr.error = WriteResult::REMOTE_CLOSED;
-				return wr;
-			}
-
-			to_write -= bytes_wrote;
-			wr.bytes_wrote += bytes_wrote;
-		}
-		return wr;
-	}
+	ReadResult read_nonblock(void* data, u32 size);
 
 	/// Writes @a size bytes and returns the result.
-	WriteResult write_nonblock(const void* data, u32 size)
-	{
-		set_blocking(false);
-		return write_internal(data, size);
-	}
+	WriteResult write(const void* data, u32 size);
 
 	/// Writes @a size bytes and returns the result.
-	WriteResult write(const void* data, u32 size)
-	{
-		set_blocking(true);
-		return write_internal(data, size);
-	}
+	WriteResult write_nonblock(const void* data, u32 size);
 
 	/// Sets whether the socket is @a blocking.
-	void set_blocking(bool blocking)
-	{
-#if CROWN_PLATFORM_POSIX
-		int flags = fcntl(_socket, F_GETFL, 0);
-		fcntl(_socket, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : O_NONBLOCK);
-#elif CROWN_PLATFORM_WINDOWS
-		u_long non_blocking = blocking ? 0 : 1;
-		ioctlsocket(_socket, FIONBIO, &non_blocking);
-#endif
-	}
+	void set_blocking(bool blocking);
 
 	/// Sets whether the socket should @a reuse a busy port.
-	void set_reuse_address(bool reuse)
-	{
-		int optval = (int)reuse;
-		int err = setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&optval, sizeof(optval));
-		CE_ASSERT(err == 0, "setsockopt: last_error() = %d", last_error());
-		CE_UNUSED(err);
-	}
+	void set_reuse_address(bool reuse);
 
 	/// Sets the timeout to the given @a seconds.
-	void set_timeout(u32 seconds)
-	{
-		struct timeval timeout;
-		timeout.tv_sec = seconds;
-		timeout.tv_usec = 0;
-
-		int err = setsockopt(_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
-		CE_ASSERT(err == 0, "setsockopt: last_error(): %d", last_error());
-		err = setsockopt(_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
-		CE_ASSERT(err == 0, "setsockopt: last_error(): %d", last_error());
-		CE_UNUSED(err);
-	}
+	void set_timeout(u32 seconds);
 };
 
 } // namespace crown

+ 1 - 0
src/device/main_linux.cpp

@@ -17,6 +17,7 @@
 #include "unit_tests.h"
 #include "window.h"
 #include <bgfx/bgfxplatform.h>
+#include <fcntl.h>  // O_RDONLY, ...
 #include <stdlib.h>
 #include <string.h> // memset
 #include <X11/extensions/Xrandr.h>

+ 27 - 25
src/lua/lua_api.cpp

@@ -1893,7 +1893,7 @@ static int render_world_sprite_create(lua_State* L)
 static int render_world_sprite_destroy(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->sprite_destroy(stack.get_sprite_instance(2));
+	stack.get_render_world(1)->sprite_destroy(stack.get_unit(2), stack.get_sprite_instance(3));
 	return 0;
 }
 
@@ -1912,28 +1912,28 @@ static int render_world_sprite_instances(lua_State* L)
 static int render_world_sprite_set_visible(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->sprite_set_visible(stack.get_sprite_instance(2), stack.get_bool(3));
+	stack.get_render_world(1)->sprite_set_visible(stack.get_unit(2), stack.get_bool(3));
 	return 0;
 }
 
 static int render_world_sprite_set_frame(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->sprite_set_frame(stack.get_sprite_instance(2), stack.get_int(3));
+	stack.get_render_world(1)->sprite_set_frame(stack.get_unit(2), stack.get_int(3));
 	return 0;
 }
 
 static int render_world_sprite_flip_x(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->sprite_flip_x(stack.get_sprite_instance(2), stack.get_bool(3));
+	stack.get_render_world(1)->sprite_flip_x(stack.get_unit(2), stack.get_bool(3));
 	return 0;
 }
 
 static int render_world_sprite_flip_y(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->sprite_flip_y(stack.get_sprite_instance(2), stack.get_bool(3));
+	stack.get_render_world(1)->sprite_flip_y(stack.get_unit(2), stack.get_bool(3));
 	return 0;
 }
 
@@ -1941,7 +1941,7 @@ static int render_world_sprite_raycast(lua_State* L)
 {
 	LuaStack stack(L);
 	RenderWorld* rw = stack.get_render_world(1);
-	float t = rw->sprite_raycast(stack.get_sprite_instance(2)
+	float t = rw->sprite_raycast(stack.get_unit(2)
 		, stack.get_vector3(3)
 		, stack.get_vector3(4)
 		);
@@ -1973,7 +1973,9 @@ static int render_world_light_create(lua_State* L)
 static int render_world_light_destroy(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->light_destroy(stack.get_light_instance(2));
+	stack.get_render_world(1)->light_destroy(stack.get_unit(2)
+		, stack.get_light_instance(3)
+		);
 	return 0;
 }
 
@@ -1992,7 +1994,7 @@ static int render_world_light_instances(lua_State* L)
 static int render_world_light_type(lua_State* L)
 {
 	LuaStack stack(L);
-	LightType::Enum type = stack.get_render_world(1)->light_type(stack.get_light_instance(2));
+	LightType::Enum type = stack.get_render_world(1)->light_type(stack.get_unit(2));
 	stack.push_string(s_light[type].name);
 	return 1;
 }
@@ -2000,38 +2002,31 @@ static int render_world_light_type(lua_State* L)
 static int render_world_light_color(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.push_color4(stack.get_render_world(1)->light_color(stack.get_light_instance(2)));
+	stack.push_color4(stack.get_render_world(1)->light_color(stack.get_unit(2)));
 	return 1;
 }
 
 static int render_world_light_range(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.push_float(stack.get_render_world(1)->light_range(stack.get_light_instance(2)));
+	stack.push_float(stack.get_render_world(1)->light_range(stack.get_unit(2)));
 	return 1;
 }
 
 static int render_world_light_intensity(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.push_float(stack.get_render_world(1)->light_intensity(stack.get_light_instance(2)));
+	stack.push_float(stack.get_render_world(1)->light_intensity(stack.get_unit(2)));
 	return 1;
 }
 
 static int render_world_light_spot_angle(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.push_float(stack.get_render_world(1)->light_spot_angle(stack.get_light_instance(2)));
+	stack.push_float(stack.get_render_world(1)->light_spot_angle(stack.get_unit(2)));
 	return 1;
 }
 
-static int render_world_light_debug_draw(lua_State* L)
-{
-	LuaStack stack(L);
-	stack.get_render_world(1)->light_debug_draw(stack.get_light_instance(2), *stack.get_debug_line(3));
-	return 0;
-}
-
 static int render_world_light_set_type(lua_State* L)
 {
 	LuaStack stack(L);
@@ -2040,35 +2035,42 @@ static int render_world_light_set_type(lua_State* L)
 	const LightType::Enum lt = name_to_light_type(name);
 	LUA_ASSERT(lt != LightType::COUNT, stack, "Unknown light type: '%s'", name);
 
-	stack.get_render_world(1)->light_set_type(stack.get_light_instance(2), lt);
+	stack.get_render_world(1)->light_set_type(stack.get_unit(2), lt);
 	return 0;
 }
 
 static int render_world_light_set_color(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->light_set_color(stack.get_light_instance(2), stack.get_color4(3));
+	stack.get_render_world(1)->light_set_color(stack.get_unit(2), stack.get_color4(3));
 	return 0;
 }
 
 static int render_world_light_set_range(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->light_set_range(stack.get_light_instance(2), stack.get_float(3));
+	stack.get_render_world(1)->light_set_range(stack.get_unit(2), stack.get_float(3));
 	return 0;
 }
 
 static int render_world_light_set_intensity(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->light_set_intensity(stack.get_light_instance(2), stack.get_float(3));
+	stack.get_render_world(1)->light_set_intensity(stack.get_unit(2), stack.get_float(3));
 	return 0;
 }
 
 static int render_world_light_set_spot_angle(lua_State* L)
 {
 	LuaStack stack(L);
-	stack.get_render_world(1)->light_set_spot_angle(stack.get_light_instance(2), stack.get_float(3));
+	stack.get_render_world(1)->light_set_spot_angle(stack.get_unit(2), stack.get_float(3));
+	return 0;
+}
+
+static int render_world_light_debug_draw(lua_State* L)
+{
+	LuaStack stack(L);
+	stack.get_render_world(1)->light_debug_draw(stack.get_unit(2), *stack.get_debug_line(3));
 	return 0;
 }
 
@@ -3399,12 +3401,12 @@ void load_api(LuaEnvironment& env)
 	env.add_module_function("RenderWorld", "light_range",          render_world_light_range);
 	env.add_module_function("RenderWorld", "light_intensity",      render_world_light_intensity);
 	env.add_module_function("RenderWorld", "light_spot_angle",     render_world_light_spot_angle);
-	env.add_module_function("RenderWorld", "light_debug_draw",     render_world_light_debug_draw);
 	env.add_module_function("RenderWorld", "light_set_type",       render_world_light_set_type);
 	env.add_module_function("RenderWorld", "light_set_color",      render_world_light_set_color);
 	env.add_module_function("RenderWorld", "light_set_range",      render_world_light_set_range);
 	env.add_module_function("RenderWorld", "light_set_intensity",  render_world_light_set_intensity);
 	env.add_module_function("RenderWorld", "light_set_spot_angle", render_world_light_set_spot_angle);
+	env.add_module_function("RenderWorld", "light_debug_draw",     render_world_light_debug_draw);
 	env.add_module_function("RenderWorld", "enable_debug_drawing", render_world_enable_debug_drawing);
 
 	env.add_module_function("PhysicsWorld", "actor_instances",               physics_world_actor_instances);

+ 84 - 65
src/world/render_world.cpp

@@ -127,57 +127,63 @@ f32 RenderWorld::mesh_raycast(MeshInstance i, const Vector3& from, const Vector3
 		);
 }
 
-SpriteInstance RenderWorld::sprite_create(UnitId id, const SpriteRendererDesc& srd, const Matrix4x4& tr)
+SpriteInstance RenderWorld::sprite_create(UnitId unit, const SpriteRendererDesc& srd, const Matrix4x4& tr)
 {
 	const SpriteResource* sr = (const SpriteResource*)_resource_manager->get(RESOURCE_TYPE_SPRITE, srd.sprite_resource);
 	_material_manager->create_material(srd.material_resource);
 
-	return _sprite_manager.create(id, sr, srd.material_resource, tr);
+	return _sprite_manager.create(unit, sr, srd.material_resource, tr);
 }
 
-void RenderWorld::sprite_destroy(SpriteInstance i)
+void RenderWorld::sprite_destroy(UnitId unit, SpriteInstance /*i*/)
 {
+	SpriteInstance i = _sprite_manager.sprite(unit);
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
 	_sprite_manager.destroy(i);
 }
 
-SpriteInstance RenderWorld::sprite_instances(UnitId id)
+SpriteInstance RenderWorld::sprite_instances(UnitId unit)
 {
-	return _sprite_manager.sprite(id);
+	return _sprite_manager.sprite(unit);
 }
 
-void RenderWorld::sprite_set_material(SpriteInstance i, StringId64 id)
+void RenderWorld::sprite_set_material(UnitId unit, StringId64 id)
 {
+	SpriteInstance i = _sprite_manager.sprite(unit);
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
 	_sprite_manager._data.material[i.i] = id;
 }
 
-void RenderWorld::sprite_set_frame(SpriteInstance i, u32 index)
+void RenderWorld::sprite_set_frame(UnitId unit, u32 index)
 {
+	SpriteInstance i = _sprite_manager.sprite(unit);
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
 	_sprite_manager._data.frame[i.i] = index;
 }
 
-void RenderWorld::sprite_set_visible(SpriteInstance i, bool visible)
+void RenderWorld::sprite_set_visible(UnitId unit, bool visible)
 {
+	SpriteInstance i = _sprite_manager.sprite(unit);
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
 }
 
-void RenderWorld::sprite_flip_x(SpriteInstance i, bool flip)
+void RenderWorld::sprite_flip_x(UnitId unit, bool flip)
 {
+	SpriteInstance i = _sprite_manager.sprite(unit);
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
 	_sprite_manager._data.flip_x[i.i] = flip;
 }
 
-void RenderWorld::sprite_flip_y(SpriteInstance i, bool flip)
+void RenderWorld::sprite_flip_y(UnitId unit, bool flip)
 {
+	SpriteInstance i = _sprite_manager.sprite(unit);
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
 	_sprite_manager._data.flip_y[i.i] = flip;
 }
 
-
-f32 RenderWorld::sprite_raycast(SpriteInstance i, const Vector3& from, const Vector3& dir)
+f32 RenderWorld::sprite_raycast(UnitId unit, const Vector3& from, const Vector3& dir)
 {
+	SpriteInstance i = _sprite_manager.sprite(unit);
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
 
 	const SpriteManager::SpriteInstanceData& sid = _sprite_manager._data;
@@ -207,82 +213,131 @@ f32 RenderWorld::sprite_raycast(SpriteInstance i, const Vector3& from, const Vec
 		);
 }
 
-LightInstance RenderWorld::light_create(UnitId id, const LightDesc& ld, const Matrix4x4& tr)
+LightInstance RenderWorld::light_create(UnitId unit, const LightDesc& ld, const Matrix4x4& tr)
 {
-	return _light_manager.create(id, ld, tr);
+	return _light_manager.create(unit, ld, tr);
 }
 
-void RenderWorld::light_destroy(LightInstance i)
+void RenderWorld::light_destroy(UnitId unit, LightInstance /*i*/)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	_light_manager.destroy(i);
 }
 
-LightInstance RenderWorld::light_instances(UnitId id)
+LightInstance RenderWorld::light_instances(UnitId unit)
 {
-	return _light_manager.light(id);
+	return _light_manager.light(unit);
 }
 
-Color4 RenderWorld::light_color(LightInstance i)
+Color4 RenderWorld::light_color(UnitId unit)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	return _light_manager._data.color[i.i];
 }
 
-LightType::Enum RenderWorld::light_type(LightInstance i)
+LightType::Enum RenderWorld::light_type(UnitId unit)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	return (LightType::Enum)_light_manager._data.type[i.i];
 }
 
-f32 RenderWorld::light_range(LightInstance i)
+f32 RenderWorld::light_range(UnitId unit)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	return _light_manager._data.range[i.i];
 }
 
-f32 RenderWorld::light_intensity(LightInstance i)
+f32 RenderWorld::light_intensity(UnitId unit)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	return _light_manager._data.intensity[i.i];
 }
 
-f32 RenderWorld::light_spot_angle(LightInstance i)
+f32 RenderWorld::light_spot_angle(UnitId unit)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	return _light_manager._data.spot_angle[i.i];
 }
 
-void RenderWorld::light_set_color(LightInstance i, const Color4& col)
+void RenderWorld::light_set_color(UnitId unit, const Color4& col)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	_light_manager._data.color[i.i] = col;
 }
 
-void RenderWorld::light_set_type(LightInstance i, LightType::Enum type)
+void RenderWorld::light_set_type(UnitId unit, LightType::Enum type)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	_light_manager._data.type[i.i] = type;
 }
 
-void RenderWorld::light_set_range(LightInstance i, f32 range)
+void RenderWorld::light_set_range(UnitId unit, f32 range)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	_light_manager._data.range[i.i] = range;
 }
 
-void RenderWorld::light_set_intensity(LightInstance i, f32 intensity)
+void RenderWorld::light_set_intensity(UnitId unit, f32 intensity)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	_light_manager._data.intensity[i.i] = intensity;
 }
 
-void RenderWorld::light_set_spot_angle(LightInstance i, f32 angle)
+void RenderWorld::light_set_spot_angle(UnitId unit, f32 angle)
 {
+	LightInstance i = _light_manager.light(unit);
 	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
 	_light_manager._data.spot_angle[i.i] = angle;
 }
 
+void RenderWorld::light_debug_draw(UnitId unit, DebugLine& dl)
+{
+	LightInstance i = _light_manager.light(unit);
+	CE_ASSERT(i.i < _light_manager._data.size, "Index out of bounds");
+	LightManager::LightInstanceData& lid = _light_manager._data;
+
+	const Vector3 pos = translation(lid.world[i.i]);
+	const Vector3 dir = -z(lid.world[i.i]);
+
+	switch (lid.type[i.i])
+	{
+	case LightType::DIRECTIONAL:
+		{
+			const Vector3 end = pos + dir*3.0f;
+			dl.add_line(pos, end, COLOR4_YELLOW);
+			dl.add_cone(pos + dir*2.8f, end, 0.1f, COLOR4_YELLOW);
+		}
+		break;
+
+	case LightType::OMNI:
+		dl.add_sphere(pos, lid.range[i.i], COLOR4_YELLOW);
+		break;
+
+	case LightType::SPOT:
+		{
+			const f32 angle  = lid.spot_angle[i.i];
+			const f32 range  = lid.range[i.i];
+			const f32 radius = tan(angle)*range;
+			dl.add_cone(pos + range*dir, pos, radius, COLOR4_YELLOW);
+		}
+		break;
+
+	default:
+		CE_FATAL("Unknown light type");
+		break;
+	}
+}
+
 void RenderWorld::update_transforms(const UnitId* begin, const UnitId* end, const Matrix4x4* world)
 {
 	MeshManager::MeshInstanceData& mid = _mesh_manager._data;
@@ -424,42 +479,6 @@ void RenderWorld::render(const Matrix4x4& view, const Matrix4x4& projection)
 	}
 }
 
-void RenderWorld::light_debug_draw(LightInstance i, DebugLine& dl)
-{
-	LightManager::LightInstanceData& lid = _light_manager._data;
-
-	const Vector3 pos = translation(lid.world[i.i]);
-	const Vector3 dir = -z(lid.world[i.i]);
-
-	switch (lid.type[i.i])
-	{
-	case LightType::DIRECTIONAL:
-		{
-			const Vector3 end = pos + dir*3.0f;
-			dl.add_line(pos, end, COLOR4_YELLOW);
-			dl.add_cone(pos + dir*2.8f, end, 0.1f, COLOR4_YELLOW);
-		}
-		break;
-
-	case LightType::OMNI:
-		dl.add_sphere(pos, lid.range[i.i], COLOR4_YELLOW);
-		break;
-
-	case LightType::SPOT:
-		{
-			const f32 angle  = lid.spot_angle[i.i];
-			const f32 range  = lid.range[i.i];
-			const f32 radius = tan(angle)*range;
-			dl.add_cone(pos + range*dir, pos, radius, COLOR4_YELLOW);
-		}
-		break;
-
-	default:
-		CE_FATAL("Unknown light type");
-		break;
-	}
-}
-
 void RenderWorld::debug_draw(DebugLine& dl)
 {
 	if (!_debug_drawing)
@@ -503,14 +522,14 @@ void RenderWorld::unit_destroyed_callback(UnitId id)
 		SpriteInstance first = sprite_instances(id);
 
 		if (_sprite_manager.is_valid(first))
-			sprite_destroy(first);
+			sprite_destroy(id, first);
 	}
 
 	{
 		LightInstance first = light_instances(id);
 
 		if (_light_manager.is_valid(first))
-			light_destroy(first);
+			light_destroy(id, first);
 	}
 }
 

+ 42 - 42
src/world/render_world.h

@@ -50,69 +50,72 @@ public:
 	/// Creates a new sprite instance.
 	SpriteInstance sprite_create(UnitId id, const SpriteRendererDesc& srd, const Matrix4x4& tr);
 
-	/// Destroys the sprite @a i.
-	void sprite_destroy(SpriteInstance i);
+	/// Destroys the sprite of the @a unit.
+	void sprite_destroy(UnitId unit, SpriteInstance i);
 
-	/// Returns the sprite instances of the unit @a id.
-	SpriteInstance sprite_instances(UnitId id);
+	/// Returns the sprite instances of the @a unit.
+	SpriteInstance sprite_instances(UnitId unit);
 
-	/// Sets the material @a id of the sprite @a i.
-	void sprite_set_material(SpriteInstance i, StringId64 id);
+	/// Sets the material @a id of the sprite.
+	void sprite_set_material(UnitId unit, StringId64 id);
 
-	/// Sets the frame @a index of the sprite @a i.
-	void sprite_set_frame(SpriteInstance i, u32 index);
+	/// Sets the frame @a index of the sprite.
+	void sprite_set_frame(UnitId unit, u32 index);
 
-	/// Sets whether the sprite @a i is @a visible.
-	void sprite_set_visible(SpriteInstance i, bool visible);
+	/// Sets whether the sprite is @a visible.
+	void sprite_set_visible(UnitId unit, bool visible);
 
 	/// Sets whether to flip the sprite on the x-axis.
-	void sprite_flip_x(SpriteInstance i, bool flip);
+	void sprite_flip_x(UnitId unit, bool flip);
 
 	/// Sets whether to flip the sprite on the y-axis.
-	void sprite_flip_y(SpriteInstance i, bool flip);
+	void sprite_flip_y(UnitId unit, bool flip);
 
-	/// Returns the distance along ray (from, dir) to intersection point with sprite @a i
+	/// Returns the distance along ray (from, dir) to intersection point with sprite
 	/// or -1.0 if no intersection.
-	f32 sprite_raycast(SpriteInstance i, const Vector3& from, const Vector3& dir);
+	f32 sprite_raycast(UnitId unit, const Vector3& from, const Vector3& dir);
 
 	/// Creates a new light instance.
-	LightInstance light_create(UnitId id, const LightDesc& ld, const Matrix4x4& tr);
+	LightInstance light_create(UnitId unit, const LightDesc& ld, const Matrix4x4& tr);
 
-	/// Destroys the light @a i.
-	void light_destroy(LightInstance i);
+	/// Destroys the light.
+	void light_destroy(UnitId unit, LightInstance i);
 
-	/// Returns the light of the unit @a id.
-	LightInstance light_instances(UnitId id);
+	/// Returns the light of the @a unit.
+	LightInstance light_instances(UnitId unit);
 
-	/// Returns the type of the light @a i.
-	LightType::Enum light_type(LightInstance i);
+	/// Returns the type of the light.
+	LightType::Enum light_type(UnitId unit);
 
-	/// Returns the color of the light @a i.
-	Color4 light_color(LightInstance i);
+	/// Returns the color of the light.
+	Color4 light_color(UnitId unit);
 
-	/// Returns the range of the light @a i.
-	f32 light_range(LightInstance i);
+	/// Returns the range of the light.
+	f32 light_range(UnitId unit);
 
-	/// Returns the intensity of the light @a i.
-	f32 light_intensity(LightInstance i);
+	/// Returns the intensity of the light.
+	f32 light_intensity(UnitId unit);
 
-	/// Returns the spot angle of the light @a i.
-	f32 light_spot_angle(LightInstance i);
+	/// Returns the spot angle of the light.
+	f32 light_spot_angle(UnitId unit);
 
-	/// Sets the @a type of the light @a i.
-	void light_set_type(LightInstance i, LightType::Enum type);
+	/// Sets the @a type of the light.
+	void light_set_type(UnitId unit, LightType::Enum type);
 
-	/// Sets the @a color of the light @a i.
-	void light_set_color(LightInstance i, const Color4& color);
+	/// Sets the @a color of the light.
+	void light_set_color(UnitId unit, const Color4& color);
 
-	/// Sets the @a range of the light @a i.
-	void light_set_range(LightInstance i, f32 range);
+	/// Sets the @a range of the light.
+	void light_set_range(UnitId unit, f32 range);
 
-	/// Sets the @a intensity of the light @a i.
-	void light_set_intensity(LightInstance i, f32 intensity);
+	/// Sets the @a intensity of the light.
+	void light_set_intensity(UnitId unit, f32 intensity);
 
-	/// Sets the spot @a angle of the light @a i.
-	void light_set_spot_angle(LightInstance i, f32 angle);
+	/// Sets the spot @a angle of the light.
+	void light_set_spot_angle(UnitId unit, f32 angle);
+
+	/// Fills @a dl with debug lines from the light.
+	void light_debug_draw(UnitId unit, DebugLine& dl);
 
 	void update_transforms(const UnitId* begin, const UnitId* end, const Matrix4x4* world);
 
@@ -121,9 +124,6 @@ public:
 	/// Sets whether to @a enable debug drawing
 	void enable_debug_drawing(bool enable);
 
-	/// Fills @a dl with debug lines from light @a i.
-	void light_debug_draw(LightInstance i, DebugLine& dl);
-
 	/// Fills @a dl with debug lines
 	void debug_draw(DebugLine& dl);