1/**************************************************************************/
2/* camera_server.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "camera_server.h"
32#include "core/variant/typed_array.h"
33#include "rendering_server.h"
34#include "servers/camera/camera_feed.h"
35
36////////////////////////////////////////////////////////
37// CameraServer
38
39CameraServer::CreateFunc CameraServer::create_func = nullptr;
40
41void CameraServer::_bind_methods() {
42 ClassDB::bind_method(D_METHOD("get_feed", "index"), &CameraServer::get_feed);
43 ClassDB::bind_method(D_METHOD("get_feed_count"), &CameraServer::get_feed_count);
44 ClassDB::bind_method(D_METHOD("feeds"), &CameraServer::get_feeds);
45
46 ClassDB::bind_method(D_METHOD("add_feed", "feed"), &CameraServer::add_feed);
47 ClassDB::bind_method(D_METHOD("remove_feed", "feed"), &CameraServer::remove_feed);
48
49 ADD_SIGNAL(MethodInfo("camera_feed_added", PropertyInfo(Variant::INT, "id")));
50 ADD_SIGNAL(MethodInfo("camera_feed_removed", PropertyInfo(Variant::INT, "id")));
51
52 BIND_ENUM_CONSTANT(FEED_RGBA_IMAGE);
53 BIND_ENUM_CONSTANT(FEED_YCBCR_IMAGE);
54 BIND_ENUM_CONSTANT(FEED_Y_IMAGE);
55 BIND_ENUM_CONSTANT(FEED_CBCR_IMAGE);
56};
57
58CameraServer *CameraServer::singleton = nullptr;
59
60CameraServer *CameraServer::get_singleton() {
61 return singleton;
62};
63
64int CameraServer::get_free_id() {
65 bool id_exists = true;
66 int newid = 0;
67
68 // find a free id
69 while (id_exists) {
70 newid++;
71 id_exists = false;
72 for (int i = 0; i < feeds.size() && !id_exists; i++) {
73 if (feeds[i]->get_id() == newid) {
74 id_exists = true;
75 };
76 };
77 };
78
79 return newid;
80};
81
82int CameraServer::get_feed_index(int p_id) {
83 for (int i = 0; i < feeds.size(); i++) {
84 if (feeds[i]->get_id() == p_id) {
85 return i;
86 };
87 };
88
89 return -1;
90};
91
92Ref<CameraFeed> CameraServer::get_feed_by_id(int p_id) {
93 int index = get_feed_index(p_id);
94
95 if (index == -1) {
96 return nullptr;
97 } else {
98 return feeds[index];
99 }
100};
101
102void CameraServer::add_feed(const Ref<CameraFeed> &p_feed) {
103 ERR_FAIL_COND(p_feed.is_null());
104
105 // add our feed
106 feeds.push_back(p_feed);
107
108 print_verbose("CameraServer: Registered camera " + p_feed->get_name() + " with ID " + itos(p_feed->get_id()) + " and position " + itos(p_feed->get_position()) + " at index " + itos(feeds.size() - 1));
109
110 // let whomever is interested know
111 emit_signal(SNAME("camera_feed_added"), p_feed->get_id());
112};
113
114void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) {
115 for (int i = 0; i < feeds.size(); i++) {
116 if (feeds[i] == p_feed) {
117 int feed_id = p_feed->get_id();
118
119 print_verbose("CameraServer: Removed camera " + p_feed->get_name() + " with ID " + itos(feed_id) + " and position " + itos(p_feed->get_position()));
120
121 // remove it from our array, if this results in our feed being unreferenced it will be destroyed
122 feeds.remove_at(i);
123
124 // let whomever is interested know
125 emit_signal(SNAME("camera_feed_removed"), feed_id);
126 return;
127 };
128 };
129};
130
131Ref<CameraFeed> CameraServer::get_feed(int p_index) {
132 ERR_FAIL_INDEX_V(p_index, feeds.size(), nullptr);
133
134 return feeds[p_index];
135};
136
137int CameraServer::get_feed_count() {
138 return feeds.size();
139};
140
141TypedArray<CameraFeed> CameraServer::get_feeds() {
142 TypedArray<CameraFeed> return_feeds;
143 int cc = get_feed_count();
144 return_feeds.resize(cc);
145
146 for (int i = 0; i < feeds.size(); i++) {
147 return_feeds[i] = get_feed(i);
148 };
149
150 return return_feeds;
151};
152
153RID CameraServer::feed_texture(int p_id, CameraServer::FeedImage p_texture) {
154 int index = get_feed_index(p_id);
155 ERR_FAIL_COND_V(index == -1, RID());
156
157 Ref<CameraFeed> feed = get_feed(index);
158
159 return feed->get_texture(p_texture);
160};
161
162CameraServer::CameraServer() {
163 singleton = this;
164};
165
166CameraServer::~CameraServer() {
167 singleton = nullptr;
168};
169