Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||||
#
|
||||
|
||||
|
||||
ADD_SUBDIRECTORY(Common)
|
||||
ADD_SUBDIRECTORY(Gui)
|
||||
|
||||
#
|
||||
# Gui Plugin Interface
|
||||
#
|
||||
ADD_INTERFACE_LIBRARY(BdvViewerGuiPluginInterface
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bdv_viewer_gui_plugin_interface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
GuiPluginInterface
|
||||
)
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
Use of this software is granted under one of the following two licenses,
|
||||
to be chosen freely by the user.
|
||||
|
||||
1. Boost Software License - Version 1.0 - August 17th, 2003
|
||||
===============================================================================
|
||||
|
||||
Copyright (c) 2006, 2007 Marcin Kalicinski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
2. The MIT License
|
||||
===============================================================================
|
||||
|
||||
Copyright (c) 2006, 2007 Marcin Kalicinski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
+406
@@ -0,0 +1,406 @@
|
||||
<html><head><style type="text/css">
|
||||
|
||||
body
|
||||
{
|
||||
font-family: sans-serif;
|
||||
font-size: 90%;
|
||||
margin: 8pt 8pt 8pt 8pt;
|
||||
text-align: justify;
|
||||
background-color: White;
|
||||
}
|
||||
|
||||
h1 { font-weight: bold; text-align: left; }
|
||||
h2 { font: 140% sans-serif; font-weight: bold; text-align: left; }
|
||||
h3 { font: 120% sans-serif; font-weight: bold; text-align: left; }
|
||||
h4 { font: bold 100% sans-serif; font-weight: bold; text-align: left; }
|
||||
h5 { font: italic 100% sans-serif; font-weight: bold; text-align: left; }
|
||||
h6 { font: small-caps 100% sans-serif; font-weight: bold; text-align: left; }
|
||||
|
||||
code
|
||||
{
|
||||
font-family: "Courier New", Courier, mono;
|
||||
}
|
||||
|
||||
pre
|
||||
{
|
||||
border-top: gray 0.5pt solid;
|
||||
border-right: gray 0.5pt solid;
|
||||
border-left: gray 0.5pt solid;
|
||||
border-bottom: gray 0.5pt solid;
|
||||
padding-top: 2pt;
|
||||
padding-right: 2pt;
|
||||
padding-left: 2pt;
|
||||
padding-bottom: 2pt;
|
||||
display: block;
|
||||
font-family: "courier new", courier, mono;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
color: #000080;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.reference-header
|
||||
{
|
||||
border-top: gray 0.5pt solid;
|
||||
border-right: gray 0.5pt solid;
|
||||
border-left: gray 0.5pt solid;
|
||||
border-bottom: gray 0.5pt solid;
|
||||
padding-top: 2pt;
|
||||
padding-right: 2pt;
|
||||
padding-left: 2pt;
|
||||
padding-bottom: 2pt;
|
||||
background-color: #dedede;
|
||||
}
|
||||
|
||||
.parameter-name
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.indented
|
||||
{
|
||||
margin-left: 0.5cm;
|
||||
}
|
||||
|
||||
a.toc1
|
||||
{
|
||||
margin-left: 0.0cm;
|
||||
}
|
||||
|
||||
a.toc2
|
||||
{
|
||||
margin-left: 0.75cm;
|
||||
}
|
||||
|
||||
a.toc3
|
||||
{
|
||||
margin-left: 1.5cm;
|
||||
}
|
||||
|
||||
</style></head><body><h1>RAPIDXML Manual</h1><h3>Version 1.13</h3><detaileddescription xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><para><i>Copyright (C) 2006, 2009 Marcin Kalicinski</i><br/><i>See accompanying file <a href="license.txt">license.txt</a> for license information.</i><hr/><h2 level="2">Table of Contents</h2></para><para><toc><toc-contents><a href="#namespacerapidxml_1what_is_rapidxml" class="toc1">1. What is RapidXml?</a><br/><a href="#namespacerapidxml_1dependencies_and_compatibility" class="toc2">1.1 Dependencies And Compatibility</a><br/><a href="#namespacerapidxml_1character_types_and_encodings" class="toc2">1.2 Character Types And Encodings</a><br/><a href="#namespacerapidxml_1error_handling" class="toc2">1.3 Error Handling</a><br/><a href="#namespacerapidxml_1memory_allocation" class="toc2">1.4 Memory Allocation</a><br/><a href="#namespacerapidxml_1w3c_compliance" class="toc2">1.5 W3C Compliance</a><br/><a href="#namespacerapidxml_1api_design" class="toc2">1.6 API Design</a><br/><a href="#namespacerapidxml_1reliability" class="toc2">1.7 Reliability</a><br/><a href="#namespacerapidxml_1acknowledgements" class="toc2">1.8 Acknowledgements</a><br/><a href="#namespacerapidxml_1two_minute_tutorial" class="toc1">2. Two Minute Tutorial</a><br/><a href="#namespacerapidxml_1parsing" class="toc2">2.1 Parsing</a><br/><a href="#namespacerapidxml_1accessing_dom_tree" class="toc2">2.2 Accessing The DOM Tree</a><br/><a href="#namespacerapidxml_1modifying_dom_tree" class="toc2">2.3 Modifying The DOM Tree</a><br/><a href="#namespacerapidxml_1printing" class="toc2">2.4 Printing XML</a><br/><a href="#namespacerapidxml_1differences" class="toc1">3. Differences From Regular XML Parsers</a><br/><a href="#namespacerapidxml_1lifetime_of_source_text" class="toc2">3.1 Lifetime Of Source Text</a><br/><a href="#namespacerapidxml_1ownership_of_strings" class="toc2">3.2 Ownership Of Strings</a><br/><a href="#namespacerapidxml_1destructive_non_destructive" class="toc2">3.3 Destructive Vs Non-Destructive Mode</a><br/><a href="#namespacerapidxml_1performance" class="toc1">4. Performance</a><br/><a href="#namespacerapidxml_1performance_charts" class="toc2">4.1 Comparison With Other Parsers</a><br/><a href="#namespacerapidxml_1reference" class="toc1">5. Reference</a><br/></toc-contents></toc><br/></para><sect1><h2 id="namespacerapidxml_1what_is_rapidxml">1. What is RapidXml?</h2><para><a href="http://rapidxml.sourceforge.net">RapidXml</a> is an attempt to create the fastest XML DOM parser possible, while retaining useability, portability and reasonable W3C compatibility. It is an in-situ parser written in C++, with parsing speed approaching that of <code>strlen()</code> function executed on the same data. <br/><br/>
|
||||
Entire parser is contained in a single header file, so no building or linking is neccesary. To use it you just need to copy <code>rapidxml.hpp</code> file to a convenient place (such as your project directory), and include it where needed. You may also want to use printing functions contained in header <code>rapidxml_print.hpp</code>.</para><sect2><h3 id="namespacerapidxml_1dependencies_and_compatibility">1.1 Dependencies And Compatibility</h3><para>RapidXml has <i>no dependencies</i> other than a very small subset of standard C++ library (<code><cassert></code>, <code><cstdlib></code>, <code><new></code> and <code><exception></code>, unless exceptions are disabled). It should compile on any reasonably conformant compiler, and was tested on Visual C++ 2003, Visual C++ 2005, Visual C++ 2008, gcc 3, gcc 4, and Comeau 4.3.3. Care was taken that no warnings are produced on these compilers, even with highest warning levels enabled.</para></sect2><sect2><h3 id="namespacerapidxml_1character_types_and_encodings">1.2 Character Types And Encodings</h3><para>RapidXml is character type agnostic, and can work both with narrow and wide characters. Current version does not fully support UTF-16 or UTF-32, so use of wide characters is somewhat incapacitated. However, it should succesfully parse <code>wchar_t</code> strings containing UTF-16 or UTF-32 if endianness of the data matches that of the machine. UTF-8 is fully supported, including all numeric character references, which are expanded into appropriate UTF-8 byte sequences (unless you enable parse_no_utf8 flag). <br/><br/>
|
||||
Note that RapidXml performs no decoding - strings returned by name() and value() functions will contain text encoded using the same encoding as source file. Rapidxml understands and expands the following character references: <code>&apos; &amp; &quot; &lt; &gt; &#...;</code> Other character references are not expanded.</para></sect2><sect2><h3 id="namespacerapidxml_1error_handling">1.3 Error Handling</h3><para>By default, RapidXml uses C++ exceptions to report errors. If this behaviour is undesirable, RAPIDXML_NO_EXCEPTIONS can be defined to suppress exception code. See <a href="#classrapidxml_1_1parse__error" kindref="compound">parse_error</a> class and <a href="#namespacerapidxml_ff5d67f74437199d316d2b2660653ae1_1ff5d67f74437199d316d2b2660653ae1" kindref="member">parse_error_handler()</a> function for more information.</para></sect2><sect2><h3 id="namespacerapidxml_1memory_allocation">1.4 Memory Allocation</h3><para>RapidXml uses a special memory pool object to allocate nodes and attributes, because direct allocation using <code>new</code> operator would be far too slow. Underlying memory allocations performed by the pool can be customized by use of <a href="#classrapidxml_1_1memory__pool_c0a55a6ef0837dca67572e357100d78a_1c0a55a6ef0837dca67572e357100d78a" kindref="member">memory_pool::set_allocator()</a> function. See class <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a> for more information.</para></sect2><sect2><h3 id="namespacerapidxml_1w3c_compliance">1.5 W3C Compliance</h3><para>RapidXml is not a W3C compliant parser, primarily because it ignores DOCTYPE declarations. There is a number of other, minor incompatibilities as well. Still, it can successfully parse and produce complete trees of all valid XML files in W3C conformance suite (over 1000 files specially designed to find flaws in XML processors). In destructive mode it performs whitespace normalization and character entity substitution for a small set of built-in entities.</para></sect2><sect2><h3 id="namespacerapidxml_1api_design">1.6 API Design</h3><para>RapidXml API is minimalistic, to reduce code size as much as possible, and facilitate use in embedded environments. Additional convenience functions are provided in separate headers: <code>rapidxml_utils.hpp</code> and <code><a href="#rapidxml__print_8hpp" kindref="compound">rapidxml_print.hpp</a></code>. Contents of these headers is not an essential part of the library, and is currently not documented (otherwise than with comments in code).</para></sect2><sect2><h3 id="namespacerapidxml_1reliability">1.7 Reliability</h3><para>RapidXml is very robust and comes with a large harness of unit tests. Special care has been taken to ensure stability of the parser no matter what source text is thrown at it. One of the unit tests produces 100,000 randomly corrupted variants of XML document, which (when uncorrupted) contains all constructs recognized by RapidXml. RapidXml passes this test when it correctly recognizes that errors have been introduced, and does not crash or loop indefinitely. <br/><br/>
|
||||
Another unit test puts RapidXml head-to-head with another, well estabilished XML parser, and verifies that their outputs match across a wide variety of small and large documents. <br/><br/>
|
||||
Yet another test feeds RapidXml with over 1000 test files from W3C compliance suite, and verifies that correct results are obtained. There are also additional tests that verify each API function separately, and test that various parsing modes work as expected.</para></sect2><sect2><h3 id="namespacerapidxml_1acknowledgements">1.8 Acknowledgements</h3><para>I would like to thank Arseny Kapoulkine for his work on <a href="http://code.google.com/p/pugixml">pugixml</a>, which was an inspiration for this project. Additional thanks go to Kristen Wegner for creating <a href="http://www.codeproject.com/soap/pugxml.asp">pugxml</a>, from which pugixml was derived. Janusz Wohlfeil kindly ran RapidXml speed tests on hardware that I did not have access to, allowing me to expand performance comparison table.</para></sect2></sect1><sect1><h2 id="namespacerapidxml_1two_minute_tutorial">2. Two Minute Tutorial</h2><sect2><h3 id="namespacerapidxml_1parsing">2.1 Parsing</h3><para>The following code causes RapidXml to parse a zero-terminated string named <code>text</code>: <pre>using namespace rapidxml;
|
||||
xml_document<> doc; // character type defaults to char
|
||||
doc.parse<0>(text); // 0 means default parse flags
|
||||
</pre><code>doc</code> object is now a root of DOM tree containing representation of the parsed XML. Because all RapidXml interface is contained inside namespace <code>rapidxml</code>, users must either bring contents of this namespace into scope, or fully qualify all the names. Class <a href="#classrapidxml_1_1xml__document" kindref="compound">xml_document</a> represents a root of the DOM hierarchy. By means of public inheritance, it is also an <a href="#classrapidxml_1_1xml__node" kindref="compound">xml_node</a> and a <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a>. Template parameter of <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function is used to specify parsing flags, with which you can fine-tune behaviour of the parser. Note that flags must be a compile-time constant.</para></sect2><sect2><h3 id="namespacerapidxml_1accessing_dom_tree">2.2 Accessing The DOM Tree</h3><para>To access the DOM tree, use methods of <a href="#classrapidxml_1_1xml__node" kindref="compound">xml_node</a> and <a href="#classrapidxml_1_1xml__attribute" kindref="compound">xml_attribute</a> classes: <pre>cout << "Name of my first node is: " << doc.first_node()->name() << "\n";
|
||||
xml_node<> *node = doc.first_node("foobar");
|
||||
cout << "Node foobar has value " << node->value() << "\n";
|
||||
for (xml_attribute<> *attr = node->first_attribute();
|
||||
attr; attr = attr->next_attribute())
|
||||
{
|
||||
cout << "Node foobar has attribute " << attr->name() << " ";
|
||||
cout << "with value " << attr->value() << "\n";
|
||||
}
|
||||
</pre></para></sect2><sect2><h3 id="namespacerapidxml_1modifying_dom_tree">2.3 Modifying The DOM Tree</h3><para>DOM tree produced by the parser is fully modifiable. Nodes and attributes can be added/removed, and their contents changed. The below example creates a HTML document, whose sole contents is a link to google.com website: <pre>xml_document<> doc;
|
||||
xml_node<> *node = doc.allocate_node(node_element, "a", "Google");
|
||||
doc.append_node(node);
|
||||
xml_attribute<> *attr = doc.allocate_attribute("href", "google.com");
|
||||
node->append_attribute(attr);
|
||||
</pre> One quirk is that nodes and attributes <i>do not own</i> the text of their names and values. This is because normally they only store pointers to the source text. So, when assigning a new name or value to the node, care must be taken to ensure proper lifetime of the string. The easiest way to achieve it is to allocate the string from the <a href="#classrapidxml_1_1xml__document" kindref="compound">xml_document</a> memory pool. In the above example this is not necessary, because we are only assigning character constants. But the code below uses <a href="#classrapidxml_1_1memory__pool_69729185bc59b0875192d667c47b8859_169729185bc59b0875192d667c47b8859" kindref="member">memory_pool::allocate_string()</a> function to allocate node name (which will have the same lifetime as the document), and assigns it to a new node: <pre>xml_document<> doc;
|
||||
char *node_name = doc.allocate_string(name); // Allocate string and copy name into it
|
||||
xml_node<> *node = doc.allocate_node(node_element, node_name); // Set node name to node_name
|
||||
</pre> Check <a href="#namespacerapidxml_1reference" kindref="member">Reference</a> section for description of the entire interface.</para></sect2><sect2><h3 id="namespacerapidxml_1printing">2.4 Printing XML</h3><para>You can print <code><a href="#classrapidxml_1_1xml__document" kindref="compound">xml_document</a></code> and <code><a href="#classrapidxml_1_1xml__node" kindref="compound">xml_node</a></code> objects into an XML string. Use <a href="#namespacerapidxml_b94d570fc4c4ab2423813cd0243326b1_1b94d570fc4c4ab2423813cd0243326b1" kindref="member">print()</a> function or operator <<, which are defined in <code><a href="#rapidxml__print_8hpp" kindref="compound">rapidxml_print.hpp</a></code> header. <pre>using namespace rapidxml;
|
||||
xml_document<> doc; // character type defaults to char
|
||||
// ... some code to fill the document
|
||||
|
||||
// Print to stream using operator <<
|
||||
std::cout << doc;
|
||||
|
||||
// Print to stream using print function, specifying printing flags
|
||||
print(std::cout, doc, 0); // 0 means default printing flags
|
||||
|
||||
// Print to string using output iterator
|
||||
std::string s;
|
||||
print(std::back_inserter(s), doc, 0);
|
||||
|
||||
// Print to memory buffer using output iterator
|
||||
char buffer[4096]; // You are responsible for making the buffer large enough!
|
||||
char *end = print(buffer, doc, 0); // end contains pointer to character after last printed character
|
||||
*end = 0; // Add string terminator after XML
|
||||
</pre></para></sect2></sect1><sect1><h2 id="namespacerapidxml_1differences">3. Differences From Regular XML Parsers</h2><para>RapidXml is an <i>in-situ parser</i>, which allows it to achieve very high parsing speed. In-situ means that parser does not make copies of strings. Instead, it places pointers to the <i>source text</i> in the DOM hierarchy.</para><sect2><h3 id="namespacerapidxml_1lifetime_of_source_text">3.1 Lifetime Of Source Text</h3><para>In-situ parsing requires that source text lives at least as long as the document object. If source text is destroyed, names and values of nodes in DOM tree will become destroyed as well. Additionally, whitespace processing, character entity translation, and zero-termination of strings require that source text be modified during parsing (but see non-destructive mode). This makes the text useless for further processing once it was parsed by RapidXml. <br/><br/>
|
||||
In many cases however, these are not serious issues.</para></sect2><sect2><h3 id="namespacerapidxml_1ownership_of_strings">3.2 Ownership Of Strings</h3><para>Nodes and attributes produced by RapidXml do not own their name and value strings. They merely hold the pointers to them. This means you have to be careful when setting these values manually, by using <a href="#classrapidxml_1_1xml__base_e099c291e104a0d277307fe71f5e0f9e_1e099c291e104a0d277307fe71f5e0f9e" kindref="member">xml_base::name(const Ch *)</a> or <a href="#classrapidxml_1_1xml__base_18c7469acdca771de9b4f3054053029c_118c7469acdca771de9b4f3054053029c" kindref="member">xml_base::value(const Ch *)</a> functions. Care must be taken to ensure that lifetime of the string passed is at least as long as lifetime of the node/attribute. The easiest way to achieve it is to allocate the string from <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a> owned by the document. Use <a href="#classrapidxml_1_1memory__pool_69729185bc59b0875192d667c47b8859_169729185bc59b0875192d667c47b8859" kindref="member">memory_pool::allocate_string()</a> function for this purpose.</para></sect2><sect2><h3 id="namespacerapidxml_1destructive_non_destructive">3.3 Destructive Vs Non-Destructive Mode</h3><para>By default, the parser modifies source text during the parsing process. This is required to achieve character entity translation, whitespace normalization, and zero-termination of strings. <br/><br/>
|
||||
In some cases this behaviour may be undesirable, for example if source text resides in read only memory, or is mapped to memory directly from file. By using appropriate parser flags (parse_non_destructive), source text modifications can be disabled. However, because RapidXml does in-situ parsing, it obviously has the following side-effects:<ul><li><para>no whitespace normalization is done</para></li><li><para>no entity reference translation is done</para></li><li><para>names and values are not zero-terminated, you must use <a href="#classrapidxml_1_1xml__base_0dae694c8f7e4d89f1003e2f3a15a43c_10dae694c8f7e4d89f1003e2f3a15a43c" kindref="member">xml_base::name_size()</a> and <a href="#classrapidxml_1_1xml__base_aed5ae791b7164c1ee5e649198cbb3db_1aed5ae791b7164c1ee5e649198cbb3db" kindref="member">xml_base::value_size()</a> functions to tell where they end</para></li></ul></para></sect2></sect1><sect1><h2 id="namespacerapidxml_1performance">4. Performance</h2><para>RapidXml achieves its speed through use of several techniques:<ul><li><para>In-situ parsing. When building DOM tree, RapidXml does not make copies of string data, such as node names and values. Instead, it stores pointers to interior of the source text.</para></li><li><para>Use of template metaprogramming techniques. This allows it to move much of the work to compile time. Through magic of the templates, C++ compiler generates a separate copy of parsing code for any combination of parser flags you use. In each copy, all possible decisions are made at compile time and all unused code is omitted.</para></li><li><para>Extensive use of lookup tables for parsing.</para></li><li><para>Hand-tuned C++ with profiling done on several most popular CPUs.</para></li></ul></para><para>This results in a very small and fast code: a parser which is custom tailored to exact needs with each invocation.</para><sect2><h3 id="namespacerapidxml_1performance_charts">4.1 Comparison With Other Parsers</h3><para>The table below compares speed of RapidXml to some other parsers, and to <code>strlen()</code> function executed on the same data. On a modern CPU (as of 2007), you can expect parsing throughput to be close to 1 GB/s. As a rule of thumb, parsing speed is about 50-100x faster than Xerces DOM, 30-60x faster than TinyXml, 3-12x faster than pugxml, and about 5% - 30% faster than pugixml, the fastest XML parser I know of.</para><para><ul><li><para>The test file is a real-world, 50kB large, moderately dense XML file. </para></li><li><para>All timing is done by using RDTSC instruction present in Pentium-compatible CPUs. </para></li><li><para>No profile-guided optimizations are used. </para></li><li><para>All parsers are running in their fastest modes. </para></li><li><para>The results are given in CPU cycles per character, so frequency of CPUs is irrelevant. </para></li><li><para>The results are minimum values from a large number of runs, to minimize effects of operating system activity, task switching, interrupt handling etc. </para></li><li><para>A single parse of the test file takes about 1/10th of a millisecond, so with large number of runs there is a good chance of hitting at least one no-interrupt streak, and obtaining undisturbed results. </para></li></ul><table rows="9" cols="7" border="1" cellpadding="3pt"><tr><th thead="yes"><para><center>Platform</center></para></th><th thead="yes"><para><center>Compiler</center></para></th><th thead="yes"><para>strlen() </para></th><th thead="yes"><para>RapidXml </para></th><th thead="yes"><para>pugixml 0.3 </para></th><th thead="yes"><para>pugxml </para></th><th thead="yes"><para>TinyXml </para></th></tr><tr><td thead="no"><para><center>Pentium 4</center></para></td><td thead="no"><para><center>MSVC 8.0</center></para></td><td thead="no"><para><center>2.5</center></para></td><td thead="no"><para><center>5.4</center></para></td><td thead="no"><para><center>7.0</center></para></td><td thead="no"><para><center>61.7</center></para></td><td thead="no"><para><center>298.8</center></para></td></tr><tr><td thead="no"><para><center>Pentium 4</center></para></td><td thead="no"><para><center>gcc 4.1.1</center></para></td><td thead="no"><para><center>0.8</center></para></td><td thead="no"><para><center>6.1</center></para></td><td thead="no"><para><center>9.5</center></para></td><td thead="no"><para><center>67.0</center></para></td><td thead="no"><para><center>413.2</center></para></td></tr><tr><td thead="no"><para><center>Core 2</center></para></td><td thead="no"><para><center>MSVC 8.0</center></para></td><td thead="no"><para><center>1.0</center></para></td><td thead="no"><para><center>4.5</center></para></td><td thead="no"><para><center>5.0</center></para></td><td thead="no"><para><center>24.6</center></para></td><td thead="no"><para><center>154.8</center></para></td></tr><tr><td thead="no"><para><center>Core 2</center></para></td><td thead="no"><para><center>gcc 4.1.1</center></para></td><td thead="no"><para><center>0.6</center></para></tLine truncated
|
||||
template
|
||||
<a href="#classrapidxml_1_1memory__pool">rapidxml::memory_pool</a></dt><dt class="indented">
|
||||
constructor
|
||||
<a href="#classrapidxml_1_1memory__pool_f8fb3c8f1a564f8045c40bcd07a89866_1f8fb3c8f1a564f8045c40bcd07a89866">memory_pool()</a></dt><dt class="indented">
|
||||
destructor
|
||||
<a href="#classrapidxml_1_1memory__pool_6f8c7990d9ec1ed2acf6558b238570eb_16f8c7990d9ec1ed2acf6558b238570eb">~memory_pool()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1memory__pool_750ba3c610b129ac057d817509d08f41_1750ba3c610b129ac057d817509d08f41">allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1memory__pool_462de142669e0ff649e8e615b82bf457_1462de142669e0ff649e8e615b82bf457">allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1memory__pool_69729185bc59b0875192d667c47b8859_169729185bc59b0875192d667c47b8859">allocate_string(const Ch *source=0, std::size_t size=0)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1memory__pool_95c49fcb056e9103ec906a59e3e01d76_195c49fcb056e9103ec906a59e3e01d76">clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1memory__pool_c8bb3912a3ce86b15842e79d0b421204_1c8bb3912a3ce86b15842e79d0b421204">clear()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1memory__pool_c0a55a6ef0837dca67572e357100d78a_1c0a55a6ef0837dca67572e357100d78a">set_allocator(alloc_func *af, free_func *ff)</a></dt><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><p/><p/><dt>class <a href="#classrapidxml_1_1parse__error">rapidxml::parse_error</a></dt><dt class="indented">
|
||||
constructor
|
||||
<a href="#classrapidxml_1_1parse__error_4dd8d1bdbd9221df4dcb90cafaee3332_14dd8d1bdbd9221df4dcb90cafaee3332">parse_error(const char *what, void *where)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1parse__error_ff06f49065b54a8a86e02e9a2441a8ba_1ff06f49065b54a8a86e02e9a2441a8ba">what() const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1parse__error_377be7d201d95221c318682c35377aca_1377be7d201d95221c318682c35377aca">where() const </a></dt><dt class="indented"/><dt class="indented"/><p/><dt>class
|
||||
template
|
||||
<a href="#classrapidxml_1_1xml__attribute">rapidxml::xml_attribute</a></dt><dt class="indented">
|
||||
constructor
|
||||
<a href="#classrapidxml_1_1xml__attribute_d5464aadf08269a886b730993525db34_1d5464aadf08269a886b730993525db34">xml_attribute()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__attribute_77aea7d8d996ba4f6bd61cc478a4e72d_177aea7d8d996ba4f6bd61cc478a4e72d">document() const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__attribute_5c4a98d2b75f9b41b12c110108fd55ab_15c4a98d2b75f9b41b12c110108fd55ab">previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__attribute_1b8a814d0d3a7165396b08433eee8a91_11b8a814d0d3a7165396b08433eee8a91">next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const </a></dt><dt class="indented"/><dt class="indented"/><dt class="indented"/><p/><dt>class
|
||||
template
|
||||
<a href="#classrapidxml_1_1xml__base">rapidxml::xml_base</a></dt><dt class="indented">
|
||||
constructor
|
||||
<a href="#classrapidxml_1_1xml__base_23630d2c130a9e0e3f3afa7584a9b218_123630d2c130a9e0e3f3afa7584a9b218">xml_base()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_622eade29fdf7806d3ef93ac4d90e707_1622eade29fdf7806d3ef93ac4d90e707">name() const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_0dae694c8f7e4d89f1003e2f3a15a43c_10dae694c8f7e4d89f1003e2f3a15a43c">name_size() const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_c54fa4987fb503916a7b541eb15c9c7f_1c54fa4987fb503916a7b541eb15c9c7f">value() const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_aed5ae791b7164c1ee5e649198cbb3db_1aed5ae791b7164c1ee5e649198cbb3db">value_size() const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_4e7e23d06d48126c65b1f6266acfba5c_14e7e23d06d48126c65b1f6266acfba5c">name(const Ch *name, std::size_t size)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_e099c291e104a0d277307fe71f5e0f9e_1e099c291e104a0d277307fe71f5e0f9e">name(const Ch *name)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_d9640aa3f5374673cb72a5289b6c91eb_1d9640aa3f5374673cb72a5289b6c91eb">value(const Ch *value, std::size_t size)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_18c7469acdca771de9b4f3054053029c_118c7469acdca771de9b4f3054053029c">value(const Ch *value)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__base_798e8df7ea53ade4d9f0701017dce80e_1798e8df7ea53ade4d9f0701017dce80e">parent() const </a></dt><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><p/><dt>class
|
||||
template
|
||||
<a href="#classrapidxml_1_1xml__document">rapidxml::xml_document</a></dt><dt class="indented">
|
||||
constructor
|
||||
<a href="#classrapidxml_1_1xml__document_6ce266cc52d549c42abe3a3d5e8af9ba_16ce266cc52d549c42abe3a3d5e8af9ba">xml_document()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c">parse(Ch *text)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__document_c8bb3912a3ce86b15842e79d0b421204_1c8bb3912a3ce86b15842e79d0b421204">clear()</a></dt><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><p/><p/><p/><p/><p/><p/><p/><p/><p/><dt>class
|
||||
template
|
||||
<a href="#classrapidxml_1_1xml__node">rapidxml::xml_node</a></dt><dt class="indented">
|
||||
constructor
|
||||
<a href="#classrapidxml_1_1xml__node_34c55af3504549a475e5b9dfcaa6adf5_134c55af3504549a475e5b9dfcaa6adf5">xml_node(node_type type)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_975e86937621ae4afe6a423219de30d0_1975e86937621ae4afe6a423219de30d0">type() const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_77aea7d8d996ba4f6bd61cc478a4e72d_177aea7d8d996ba4f6bd61cc478a4e72d">document() const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_7823e36687669e59c2afdf66334ef35a_17823e36687669e59c2afdf66334ef35a">first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_fcb6e2209b591a36d2dadba20d2bc7cc_1fcb6e2209b591a36d2dadba20d2bc7cc">last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_ac2f6886c0107e9d5f156e9542546df6_1ac2f6886c0107e9d5f156e9542546df6">previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_b3ead2cefecc03a813836203e3f6f38f_1b3ead2cefecc03a813836203e3f6f38f">next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_5810a09f82f8d53efbe9456286dcec83_15810a09f82f8d53efbe9456286dcec83">first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_16953d66751b5b949ee4ee2d9c0bc63a_116953d66751b5b949ee4ee2d9c0bc63a">last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const </a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_a78759bfa429fa2ab6bc5fe617cfa3cf_1a78759bfa429fa2ab6bc5fe617cfa3cf">type(node_type type)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_0c39df6617e709eb2fba11300dea63f2_10c39df6617e709eb2fba11300dea63f2">prepend_node(xml_node< Ch > *child)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_86de2e22276826089b7baed2599f8dee_186de2e22276826089b7baed2599f8dee">append_node(xml_node< Ch > *child)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_780972a57fc447250ab47cc8f421b65e_1780972a57fc447250ab47cc8f421b65e">insert_node(xml_node< Ch > *where, xml_node< Ch > *child)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_9a31d861e1bddc710839c551a5d2b3a4_19a31d861e1bddc710839c551a5d2b3a4">remove_first_node()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_87addf2bc127ee31aa4b5295d3c9b530_187addf2bc127ee31aa4b5295d3c9b530">remove_last_node()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_9316463a2201631e7e2062b17729f9cd_19316463a2201631e7e2062b17729f9cd">remove_node(xml_node< Ch > *where)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_0218147d13e41d5fa60ced4e7a7e9726_10218147d13e41d5fa60ced4e7a7e9726">remove_all_nodes()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_f6dffa513da74cc0be71a7ba84f8265e_1f6dffa513da74cc0be71a7ba84f8265e">prepend_attribute(xml_attribute< Ch > *attribute)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_8fbd4f5ef7169d493da9f8d87ac04b77_18fbd4f5ef7169d493da9f8d87ac04b77">append_attribute(xml_attribute< Ch > *attribute)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_070d5888b0557fe06a5b24961de1b988_1070d5888b0557fe06a5b24961de1b988">insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_4eea4a7f6cb484ca9944f7eafe6e1843_14eea4a7f6cb484ca9944f7eafe6e1843">remove_first_attribute()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_37d87c4d5d89fa0cf05b72ee8d4cba3b_137d87c4d5d89fa0cf05b72ee8d4cba3b">remove_last_attribute()</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_c75154db2e768c0e5b541fc8cd0775ab_1c75154db2e768c0e5b541fc8cd0775ab">remove_attribute(xml_attribute< Ch > *where)</a></dt><dt class="indented">function <a href="#classrapidxml_1_1xml__node_59e6ad4cfd5e8096c052e71d79561eda_159e6ad4cfd5e8096c052e71d79561eda">remove_all_attributes()</a></dt><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><dt class="indented"/><p/><dt>namespace <a href="#namespacerapidxml">rapidxml</a></dt><dt class="indented">enum <a href="#namespacerapidxml_6a276b85e2da28c5f9c3dbce61c55682_16a276b85e2da28c5f9c3dbce61c55682">node_type</a></dtLine truncated
|
||||
constant
|
||||
<a href="#namespacerapidxml_87e8bbab53702cf3b438bd553c10b6b9_187e8bbab53702cf3b438bd553c10b6b9">parse_no_data_nodes</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_97e2c4fdc04fae17126f9971a4fc993e_197e2c4fdc04fae17126f9971a4fc993e">parse_no_element_values</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_9cae3801e70437cbc410c24bf6be691c_19cae3801e70437cbc410c24bf6be691c">parse_no_string_terminators</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_7223b7815c4fb8b42e6e4e77e1ea6b97_17223b7815c4fb8b42e6e4e77e1ea6b97">parse_no_entity_translation</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_ccde57f6054857ee4042a1b4d98c83b9_1ccde57f6054857ee4042a1b4d98c83b9">parse_no_utf8</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_52e2c934ad9c845a5f4cc49570470556_152e2c934ad9c845a5f4cc49570470556">parse_declaration_node</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_0f7479dacbc868456d07897a8c072784_10f7479dacbc868456d07897a8c072784">parse_comment_nodes</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_8e187746ba1ca04f107951ad32df962e_18e187746ba1ca04f107951ad32df962e">parse_doctype_node</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_1c20b2b2b75711cd76423e119c49f830_11c20b2b2b75711cd76423e119c49f830">parse_pi_nodes</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_a5daff9d61c7d4eaf98e4d42efe628ee_1a5daff9d61c7d4eaf98e4d42efe628ee">parse_validate_closing_tags</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_ac1f06b1afd47b812732fb521b146fd9_1ac1f06b1afd47b812732fb521b146fd9">parse_trim_whitespace</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_88f95d4e275ba01408fefde83078651b_188f95d4e275ba01408fefde83078651b">parse_normalize_whitespace</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_45751cf2f38fd6915f35b3122b46d5b6_145751cf2f38fd6915f35b3122b46d5b6">parse_default</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_a97ba1a0a79a6d66f4eef3612508d943_1a97ba1a0a79a6d66f4eef3612508d943">parse_non_destructive</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_398c5476e76102f8bd76c10bb0abbe10_1398c5476e76102f8bd76c10bb0abbe10">parse_fastest</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_b4f2515265facb42291570307924bd57_1b4f2515265facb42291570307924bd57">parse_full</a></dt><dt class="indented">
|
||||
constant
|
||||
<a href="#namespacerapidxml_b08b8d4293c203b69ed6c5ae77ac1907_1b08b8d4293c203b69ed6c5ae77ac1907">print_no_indenting</a></dt><p/><p/><p/><p/></dl><hr/><h3 class="reference-header" id="classrapidxml_1_1memory__pool">class
|
||||
template
|
||||
rapidxml::memory_pool</h3>
|
||||
|
||||
Defined in <a href="rapidxml.hpp">rapidxml.hpp</a><br/>
|
||||
Base class for
|
||||
<a href="#classrapidxml_1_1xml__document">xml_document</a> <h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. In most cases, you will not need to use this class directly. However, if you need to create nodes manually or modify names/values of nodes, you are encouraged to use <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a> of relevant <a href="#classrapidxml_1_1xml__document" kindref="compound">xml_document</a> to allocate the memory. Not only is this faster than allocating them by using <code>new</code> operator, but also their lifetime will be tied to the lifetime of document, possibly simplyfing memory management. <br/><br/>
|
||||
Call <a href="#classrapidxml_1_1memory__pool_750ba3c610b129ac057d817509d08f41_1750ba3c610b129ac057d817509d08f41" kindref="member">allocate_node()</a> or <a href="#classrapidxml_1_1memory__pool_462de142669e0ff649e8e615b82bf457_1462de142669e0ff649e8e615b82bf457" kindref="member">allocate_attribute()</a> functions to obtain new nodes or attributes from the pool. You can also call <a href="#classrapidxml_1_1memory__pool_69729185bc59b0875192d667c47b8859_169729185bc59b0875192d667c47b8859" kindref="member">allocate_string()</a> function to allocate strings. Such strings can then be used as names or values of nodes without worrying about their lifetime. Note that there is no <code>free()</code> function -- all allocations are freed at once when <a href="#classrapidxml_1_1memory__pool_c8bb3912a3ce86b15842e79d0b421204_1c8bb3912a3ce86b15842e79d0b421204" kindref="member">clear()</a> function is called, or when the pool is destroyed. <br/><br/>
|
||||
It is also possible to create a standalone <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a>, and use it to allocate nodes, whose lifetime will not be tied to any document. <br/><br/>
|
||||
Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory. Until static memory is exhausted, no dynamic memory allocations are done. When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each, by using global <code>new[]</code> and <code>delete[]</code> operators. This behaviour can be changed by setting custom allocation routines. Use <a href="#classrapidxml_1_1memory__pool_c0a55a6ef0837dca67572e357100d78a_1c0a55a6ef0837dca67572e357100d78a" kindref="member">set_allocator()</a> function to set them. <br/><br/>
|
||||
Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes. This value defaults to the size of pointer on target architecture. <br/><br/>
|
||||
To obtain absolutely top performance from the parser, it is important that all nodes are allocated from a single, contiguous block of memory. Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code> to obtain best wasted memory to performance compromise. To do it, define their values before <a href="#rapidxml_8hpp" kindref="compound">rapidxml.hpp</a> file is included. </para><h4>Parameters</h4><dl><dt class="parameter-name">Ch</dt><dd>Character type of created nodes. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1memory__pool_f8fb3c8f1a564f8045c40bcd07a89866_1f8fb3c8f1a564f8045c40bcd07a89866">
|
||||
constructor
|
||||
memory_pool::memory_pool</h3><h4>Synopsis</h4><code class="synopsis">memory_pool();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Constructs empty pool with default allocator functions. </para><p/><h3 class="reference-header" id="classrapidxml_1_1memory__pool_6f8c7990d9ec1ed2acf6558b238570eb_16f8c7990d9ec1ed2acf6558b238570eb">
|
||||
destructor
|
||||
memory_pool::~memory_pool</h3><h4>Synopsis</h4><code class="synopsis">~memory_pool();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Destroys pool and frees all the memory. This causes memory occupied by nodes allocated by the pool to be freed. Nodes allocated from the pool are no longer valid. </para><p/><h3 class="reference-header" id="classrapidxml_1_1memory__pool_750ba3c610b129ac057d817509d08f41_1750ba3c610b129ac057d817509d08f41">function memory_pool::allocate_node</h3><h4>Synopsis</h4><code class="synopsis">xml_node<Ch>* allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Allocates a new node from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call <a href="#namespacerapidxml_ff5d67f74437199d316d2b2660653ae1_1ff5d67f74437199d316d2b2660653ae1" kindref="member">rapidxml::parse_error_handler()</a> function. </para><h4>Parameters</h4><dl><dt class="parameter-name">type</dt><dd class="parameter-def">Type of node to create. </dd></dl><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name to assign to the node, or 0 to assign no name. </dd></dl><dl><dt class="parameter-name">value</dt><dd class="parameter-def">Value to assign to the node, or 0 to assign no value. </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name to assign, or 0 to automatically calculate size from name string. </dd></dl><dl><dt class="parameter-name">value_size</dt><dd class="parameter-def">Size of value to assign, or 0 to automatically calculate size from value string. </dd></dl><h4>Returns</h4>Pointer to allocated node. This pointer will never be NULL. <p/><h3 class="reference-header" id="classrapidxml_1_1memory__pool_462de142669e0ff649e8e615b82bf457_1462de142669e0ff649e8e615b82bf457">function memory_pool::allocate_attribute</h3><h4>Synopsis</h4><code class="synopsis">xml_attribute<Ch>* allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Allocates a new attribute from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call <a href="#namespacerapidxml_ff5d67f74437199d316d2b2660653ae1_1ff5d67f74437199d316d2b2660653ae1" kindref="member">rapidxml::parse_error_handler()</a> function. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name to assign to the attribute, or 0 to assign no name. </dd></dl><dl><dt class="parameter-name">value</dt><dd class="parameter-def">Value to assign to the attribute, or 0 to assign no value. </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name to assign, or 0 to automatically calculate size from name string. </dd></dl><dl><dt class="parameter-name">value_size</dt><dd class="parameter-def">Size of value to assign, or 0 to automatically calculate size from value string. </dd></dl><h4>Returns</h4>Pointer to allocated attribute. This pointer will never be NULL. <p/><h3 class="reference-header" id="classrapidxml_1_1memory__pool_69729185bc59b0875192d667c47b8859_169729185bc59b0875192d667c47b8859">function memory_pool::allocate_string</h3><h4>Synopsis</h4><code class="synopsis">Ch* allocate_string(const Ch *source=0, std::size_t size=0);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Allocates a char array of given size from the pool, and optionally copies a given string to it. If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call <a href="#namespacerapidxml_ff5d67f74437199d316d2b2660653ae1_1ff5d67f74437199d316d2b2660653ae1" kindref="member">rapidxml::parse_error_handler()</a> function. </para><h4>Parameters</h4><dl><dt class="parameter-name">source</dt><dd class="parameter-def">String to initialize the allocated memory with, or 0 to not initialize it. </dd></dl><dl><dt class="parameter-name">size</dt><dd class="parameter-def">Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. </dd></dl><h4>Returns</h4>Pointer to allocated char array. This pointer will never be NULL. <p/><h3 class="reference-header" id="classrapidxml_1_1memory__pool_95c49fcb056e9103ec906a59e3e01d76_195c49fcb056e9103ec906a59e3e01d76">function memory_pool::clone_node</h3><h4>Synopsis</h4><code class="synopsis">xml_node<Ch>* clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Clones an <a href="#classrapidxml_1_1xml__node" kindref="compound">xml_node</a> and its hierarchy of child nodes and attributes. Nodes and attributes are allocated from this memory pool. Names and values are not cloned, they are shared between the clone and the source. Result node can be optionally specified as a second parameter, in which case its contents will be replaced with cloned source node. This is useful when you want to clone entire document. </para><h4>Parameters</h4><dl><dt class="parameter-name">source</dt><dd class="parameter-def">Node to clone. </dd></dl><dl><dt class="parameter-name">result</dt><dd class="parameter-def">Node to put results in, or 0 to automatically allocate result node </dd></dl><h4>Returns</h4>Pointer to cloned node. This pointer will never be NULL. <p/><h3 class="reference-header" id="classrapidxml_1_1memory__pool_c8bb3912a3ce86b15842e79d0b421204_1c8bb3912a3ce86b15842e79d0b421204">function memory_pool::clear</h3><h4>Synopsis</h4><code class="synopsis">void clear();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Clears the pool. This causes memory occupied by nodes allocated by the pool to be freed. Any nodes or strings allocated from the pool will no longer be valid. </para><p/><h3 class="reference-header" id="classrapidxml_1_1memory__pool_c0a55a6ef0837dca67572e357100d78a_1c0a55a6ef0837dca67572e357100d78a">function memory_pool::set_allocator</h3><h4>Synopsis</h4><code class="synopsis">void set_allocator(alloc_func *af, free_func *ff);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Sets or resets the user-defined memory allocation functions for the pool. This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. Allocation function must not return invalid pointer on failure. It should either throw, stop the program, or use <code>longjmp()</code> function to pass control to other place of program. If it returns invalid pointer, results are undefined. <br/><br/>
|
||||
User defined allocation functions must have the following forms: <br/><code><br/>
|
||||
void *allocate(std::size_t size); <br/>
|
||||
void free(void *pointer); </code><br/></para><h4>Parameters</h4><dl><dt class="parameter-name">af</dt><dd class="parameter-def">Allocation function, or 0 to restore default function </dd></dl><dl><dt class="parameter-name">ff</dt><dd class="parameter-def">Free function, or 0 to restore default function </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1parse__error">class rapidxml::parse_error</h3>
|
||||
|
||||
Defined in <a href="rapidxml.hpp">rapidxml.hpp</a><br/><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse error exception. This exception is thrown by the parser when an error occurs. Use <a href="#classrapidxml_1_1parse__error_ff06f49065b54a8a86e02e9a2441a8ba_1ff06f49065b54a8a86e02e9a2441a8ba" kindref="member">what()</a> function to get human-readable error message. Use <a href="#classrapidxml_1_1parse__error_377be7d201d95221c318682c35377aca_1377be7d201d95221c318682c35377aca" kindref="member">where()</a> function to get a pointer to position within source text where error was detected. <br/><br/>
|
||||
If throwing exceptions by the parser is undesirable, it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before <a href="#rapidxml_8hpp" kindref="compound">rapidxml.hpp</a> is included. This will cause the parser to call <a href="#namespacerapidxml_ff5d67f74437199d316d2b2660653ae1_1ff5d67f74437199d316d2b2660653ae1" kindref="member">rapidxml::parse_error_handler()</a> function instead of throwing an exception. This function must be defined by the user. <br/><br/>
|
||||
This class derives from <code>std::exception</code> class. </para><p/><h3 class="reference-header" id="classrapidxml_1_1parse__error_4dd8d1bdbd9221df4dcb90cafaee3332_14dd8d1bdbd9221df4dcb90cafaee3332">
|
||||
constructor
|
||||
parse_error::parse_error</h3><h4>Synopsis</h4><code class="synopsis">parse_error(const char *what, void *where);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Constructs parse error. </para><p/><h3 class="reference-header" id="classrapidxml_1_1parse__error_ff06f49065b54a8a86e02e9a2441a8ba_1ff06f49065b54a8a86e02e9a2441a8ba">function parse_error::what</h3><h4>Synopsis</h4><code class="synopsis">virtual const char* what() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets human readable description of error. </para><h4>Returns</h4>Pointer to null terminated description of the error. <p/><h3 class="reference-header" id="classrapidxml_1_1parse__error_377be7d201d95221c318682c35377aca_1377be7d201d95221c318682c35377aca">function parse_error::where</h3><h4>Synopsis</h4><code class="synopsis">Ch* where() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets pointer to character data where error happened. Ch should be the same as char type of <a href="#classrapidxml_1_1xml__document" kindref="compound">xml_document</a> that produced the error. </para><h4>Returns</h4>Pointer to location within the parsed string where error occured. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__attribute">class
|
||||
template
|
||||
rapidxml::xml_attribute</h3>
|
||||
|
||||
Defined in <a href="rapidxml.hpp">rapidxml.hpp</a><br/>
|
||||
Inherits from
|
||||
<a href="#classrapidxml_1_1xml__base">xml_base</a> <br/><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Class representing attribute node of XML document. Each attribute has name and value strings, which are available through <a href="#classrapidxml_1_1xml__base_622eade29fdf7806d3ef93ac4d90e707_1622eade29fdf7806d3ef93ac4d90e707" kindref="member">name()</a> and <a href="#classrapidxml_1_1xml__base_c54fa4987fb503916a7b541eb15c9c7f_1c54fa4987fb503916a7b541eb15c9c7f" kindref="member">value()</a> functions (inherited from <a href="#classrapidxml_1_1xml__base" kindref="compound">xml_base</a>). Note that after parse, both name and value of attribute will point to interior of source text used for parsing. Thus, this text must persist in memory for the lifetime of attribute. </para><h4>Parameters</h4><dl><dt class="parameter-name">Ch</dt><dd>Character type to use. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__attribute_d5464aadf08269a886b730993525db34_1d5464aadf08269a886b730993525db34">
|
||||
constructor
|
||||
xml_attribute::xml_attribute</h3><h4>Synopsis</h4><code class="synopsis">xml_attribute();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Constructs an empty attribute with the specified type. Consider using <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a> of appropriate <a href="#classrapidxml_1_1xml__document" kindref="compound">xml_document</a> if allocating attributes manually. </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__attribute_77aea7d8d996ba4f6bd61cc478a4e72d_177aea7d8d996ba4f6bd61cc478a4e72d">function xml_attribute::document</h3><h4>Synopsis</h4><code class="synopsis">xml_document<Ch>* document() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets document of which attribute is a child. </para><h4>Returns</h4>Pointer to document that contains this attribute, or 0 if there is no parent document. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__attribute_5c4a98d2b75f9b41b12c110108fd55ab_15c4a98d2b75f9b41b12c110108fd55ab">function xml_attribute::previous_attribute</h3><h4>Synopsis</h4><code class="synopsis">xml_attribute<Ch>* previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets previous attribute, optionally matching attribute name. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name, in characters, or 0 to have size calculated automatically from string </dd></dl><dl><dt class="parameter-name">case_sensitive</dt><dd class="parameter-def">Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters </dd></dl><h4>Returns</h4>Pointer to found attribute, or 0 if not found. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__attribute_1b8a814d0d3a7165396b08433eee8a91_11b8a814d0d3a7165396b08433eee8a91">function xml_attribute::next_attribute</h3><h4>Synopsis</h4><code class="synopsis">xml_attribute<Ch>* next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets next attribute, optionally matching attribute name. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name, in characters, or 0 to have size calculated automatically from string </dd></dl><dl><dt class="parameter-name">case_sensitive</dt><dd class="parameter-def">Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters </dd></dl><h4>Returns</h4>Pointer to found attribute, or 0 if not found. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__base">class
|
||||
template
|
||||
rapidxml::xml_base</h3>
|
||||
|
||||
Defined in <a href="rapidxml.hpp">rapidxml.hpp</a><br/>
|
||||
Base class for
|
||||
<a href="#classrapidxml_1_1xml__attribute">xml_attribute</a> <a href="#classrapidxml_1_1xml__node">xml_node</a> <h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Base class for <a href="#classrapidxml_1_1xml__node" kindref="compound">xml_node</a> and <a href="#classrapidxml_1_1xml__attribute" kindref="compound">xml_attribute</a> implementing common functions: <a href="#classrapidxml_1_1xml__base_622eade29fdf7806d3ef93ac4d90e707_1622eade29fdf7806d3ef93ac4d90e707" kindref="member">name()</a>, <a href="#classrapidxml_1_1xml__base_0dae694c8f7e4d89f1003e2f3a15a43c_10dae694c8f7e4d89f1003e2f3a15a43c" kindref="member">name_size()</a>, <a href="#classrapidxml_1_1xml__base_c54fa4987fb503916a7b541eb15c9c7f_1c54fa4987fb503916a7b541eb15c9c7f" kindref="member">value()</a>, <a href="#classrapidxml_1_1xml__base_aed5ae791b7164c1ee5e649198cbb3db_1aed5ae791b7164c1ee5e649198cbb3db" kindref="member">value_size()</a> and <a href="#classrapidxml_1_1xml__base_798e8df7ea53ade4d9f0701017dce80e_1798e8df7ea53ade4d9f0701017dce80e" kindref="member">parent()</a>. </para><h4>Parameters</h4><dl><dt class="parameter-name">Ch</dt><dd>Character type to use </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_23630d2c130a9e0e3f3afa7584a9b218_123630d2c130a9e0e3f3afa7584a9b218">
|
||||
constructor
|
||||
xml_base::xml_base</h3><h4>Synopsis</h4><code class="synopsis">xml_base();
|
||||
</code><p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_622eade29fdf7806d3ef93ac4d90e707_1622eade29fdf7806d3ef93ac4d90e707">function xml_base::name</h3><h4>Synopsis</h4><code class="synopsis">Ch* name() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets name of the node. Interpretation of name depends on type of node. Note that name will not be zero-terminated if <a href="#namespacerapidxml_9cae3801e70437cbc410c24bf6be691c_19cae3801e70437cbc410c24bf6be691c" kindref="member">rapidxml::parse_no_string_terminators</a> option was selected during parse. <br/><br/>
|
||||
Use <a href="#classrapidxml_1_1xml__base_0dae694c8f7e4d89f1003e2f3a15a43c_10dae694c8f7e4d89f1003e2f3a15a43c" kindref="member">name_size()</a> function to determine length of the name. </para><h4>Returns</h4>Name of node, or empty string if node has no name. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_0dae694c8f7e4d89f1003e2f3a15a43c_10dae694c8f7e4d89f1003e2f3a15a43c">function xml_base::name_size</h3><h4>Synopsis</h4><code class="synopsis">std::size_t name_size() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets size of node name, not including terminator character. This function works correctly irrespective of whether name is or is not zero terminated. </para><h4>Returns</h4>Size of node name, in characters. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_c54fa4987fb503916a7b541eb15c9c7f_1c54fa4987fb503916a7b541eb15c9c7f">function xml_base::value</h3><h4>Synopsis</h4><code class="synopsis">Ch* value() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets value of node. Interpretation of value depends on type of node. Note that value will not be zero-terminated if <a href="#namespacerapidxml_9cae3801e70437cbc410c24bf6be691c_19cae3801e70437cbc410c24bf6be691c" kindref="member">rapidxml::parse_no_string_terminators</a> option was selected during parse. <br/><br/>
|
||||
Use <a href="#classrapidxml_1_1xml__base_aed5ae791b7164c1ee5e649198cbb3db_1aed5ae791b7164c1ee5e649198cbb3db" kindref="member">value_size()</a> function to determine length of the value. </para><h4>Returns</h4>Value of node, or empty string if node has no value. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_aed5ae791b7164c1ee5e649198cbb3db_1aed5ae791b7164c1ee5e649198cbb3db">function xml_base::value_size</h3><h4>Synopsis</h4><code class="synopsis">std::size_t value_size() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets size of node value, not including terminator character. This function works correctly irrespective of whether value is or is not zero terminated. </para><h4>Returns</h4>Size of node value, in characters. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_4e7e23d06d48126c65b1f6266acfba5c_14e7e23d06d48126c65b1f6266acfba5c">function xml_base::name</h3><h4>Synopsis</h4><code class="synopsis">void name(const Ch *name, std::size_t size);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Sets name of node to a non zero-terminated string. See <a href="#namespacerapidxml_1ownership_of_strings" kindref="member">Ownership Of Strings</a> . <br/><br/>
|
||||
Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a> of the document to allocate the string - on destruction of the document the string will be automatically freed. <br/><br/>
|
||||
Size of name must be specified separately, because name does not have to be zero terminated. Use <a href="#classrapidxml_1_1xml__base_e099c291e104a0d277307fe71f5e0f9e_1e099c291e104a0d277307fe71f5e0f9e" kindref="member">name(const Ch *)</a> function to have the length automatically calculated (string must be zero terminated). </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of node to set. Does not have to be zero terminated. </dd></dl><dl><dt class="parameter-name">size</dt><dd class="parameter-def">Size of name, in characters. This does not include zero terminator, if one is present. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_e099c291e104a0d277307fe71f5e0f9e_1e099c291e104a0d277307fe71f5e0f9e">function xml_base::name</h3><h4>Synopsis</h4><code class="synopsis">void name(const Ch *name);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Sets name of node to a zero-terminated string. See also <a href="#namespacerapidxml_1ownership_of_strings" kindref="member">Ownership Of Strings</a> and <a href="#classrapidxml_1_1xml__base_4e7e23d06d48126c65b1f6266acfba5c_14e7e23d06d48126c65b1f6266acfba5c" kindref="member">xml_node::name(const Ch *, std::size_t)</a>. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of node to set. Must be zero terminated. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_d9640aa3f5374673cb72a5289b6c91eb_1d9640aa3f5374673cb72a5289b6c91eb">function xml_base::value</h3><h4>Synopsis</h4><code class="synopsis">void value(const Ch *value, std::size_t size);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Sets value of node to a non zero-terminated string. See <a href="#namespacerapidxml_1ownership_of_strings" kindref="member">Ownership Of Strings</a> . <br/><br/>
|
||||
Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a> of the document to allocate the string - on destruction of the document the string will be automatically freed. <br/><br/>
|
||||
Size of value must be specified separately, because it does not have to be zero terminated. Use <a href="#classrapidxml_1_1xml__base_18c7469acdca771de9b4f3054053029c_118c7469acdca771de9b4f3054053029c" kindref="member">value(const Ch *)</a> function to have the length automatically calculated (string must be zero terminated). <br/><br/>
|
||||
If an element has a child node of type node_data, it will take precedence over element value when printing. If you want to manipulate data of elements using values, use parser flag <a href="#namespacerapidxml_87e8bbab53702cf3b438bd553c10b6b9_187e8bbab53702cf3b438bd553c10b6b9" kindref="member">rapidxml::parse_no_data_nodes</a> to prevent creation of data nodes by the parser. </para><h4>Parameters</h4><dl><dt class="parameter-name">value</dt><dd class="parameter-def">value of node to set. Does not have to be zero terminated. </dd></dl><dl><dt class="parameter-name">size</dt><dd class="parameter-def">Size of value, in characters. This does not include zero terminator, if one is present. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_18c7469acdca771de9b4f3054053029c_118c7469acdca771de9b4f3054053029c">function xml_base::value</h3><h4>Synopsis</h4><code class="synopsis">void value(const Ch *value);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Sets value of node to a zero-terminated string. See also <a href="#namespacerapidxml_1ownership_of_strings" kindref="member">Ownership Of Strings</a> and <a href="#classrapidxml_1_1xml__base_d9640aa3f5374673cb72a5289b6c91eb_1d9640aa3f5374673cb72a5289b6c91eb" kindref="member">xml_node::value(const Ch *, std::size_t)</a>. </para><h4>Parameters</h4><dl><dt class="parameter-name">value</dt><dd class="parameter-def">Vame of node to set. Must be zero terminated. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__base_798e8df7ea53ade4d9f0701017dce80e_1798e8df7ea53ade4d9f0701017dce80e">function xml_base::parent</h3><h4>Synopsis</h4><code class="synopsis">xml_node<Ch>* parent() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets node parent. </para><h4>Returns</h4>Pointer to parent node, or 0 if there is no parent. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__document">class
|
||||
template
|
||||
rapidxml::xml_document</h3>
|
||||
|
||||
Defined in <a href="rapidxml.hpp">rapidxml.hpp</a><br/>
|
||||
Inherits from
|
||||
<a href="#classrapidxml_1_1xml__node">xml_node</a> <a href="#classrapidxml_1_1memory__pool">memory_pool</a> <br/><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">This class represents root of the DOM hierarchy. It is also an <a href="#classrapidxml_1_1xml__node" kindref="compound">xml_node</a> and a <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a> through public inheritance. Use <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">parse()</a> function to build a DOM tree from a zero-terminated XML text string. <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">parse()</a> function allocates memory for nodes and attributes by using functions of <a href="#classrapidxml_1_1xml__document" kindref="compound">xml_document</a>, which are inherited from <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a>. To access root node of the document, use the document itself, as if it was an <a href="#classrapidxml_1_1xml__node" kindref="compound">xml_node</a>. </para><h4>Parameters</h4><dl><dt class="parameter-name">Ch</dt><dd>Character type to use. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__document_6ce266cc52d549c42abe3a3d5e8af9ba_16ce266cc52d549c42abe3a3d5e8af9ba">
|
||||
constructor
|
||||
xml_document::xml_document</h3><h4>Synopsis</h4><code class="synopsis">xml_document();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Constructs empty XML document. </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c">function xml_document::parse</h3><h4>Synopsis</h4><code class="synopsis">void parse(Ch *text);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parses zero-terminated XML string according to given flags. Passed string will be modified by the parser, unless <a href="#namespacerapidxml_a97ba1a0a79a6d66f4eef3612508d943_1a97ba1a0a79a6d66f4eef3612508d943" kindref="member">rapidxml::parse_non_destructive</a> flag is used. The string must persist for the lifetime of the document. In case of error, <a href="#classrapidxml_1_1parse__error" kindref="compound">rapidxml::parse_error</a> exception will be thrown. <br/><br/>
|
||||
If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. Make sure that data is zero-terminated. <br/><br/>
|
||||
Document can be parsed into multiple times. Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. </para><h4>Parameters</h4><dl><dt class="parameter-name">text</dt><dd class="parameter-def">XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__document_c8bb3912a3ce86b15842e79d0b421204_1c8bb3912a3ce86b15842e79d0b421204">function xml_document::clear</h3><h4>Synopsis</h4><code class="synopsis">void clear();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Clears the document by deleting all nodes and clearing the memory pool. All nodes owned by document pool are destroyed. </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node">class
|
||||
template
|
||||
rapidxml::xml_node</h3>
|
||||
|
||||
Defined in <a href="rapidxml.hpp">rapidxml.hpp</a><br/>
|
||||
Inherits from
|
||||
<a href="#classrapidxml_1_1xml__base">xml_base</a> <br/>
|
||||
Base class for
|
||||
<a href="#classrapidxml_1_1xml__document">xml_document</a> <h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Class representing a node of XML document. Each node may have associated name and value strings, which are available through <a href="#classrapidxml_1_1xml__base_622eade29fdf7806d3ef93ac4d90e707_1622eade29fdf7806d3ef93ac4d90e707" kindref="member">name()</a> and <a href="#classrapidxml_1_1xml__base_c54fa4987fb503916a7b541eb15c9c7f_1c54fa4987fb503916a7b541eb15c9c7f" kindref="member">value()</a> functions. Interpretation of name and value depends on type of the node. Type of node can be determined by using <a href="#classrapidxml_1_1xml__node_975e86937621ae4afe6a423219de30d0_1975e86937621ae4afe6a423219de30d0" kindref="member">type()</a> function. <br/><br/>
|
||||
Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. Thus, this text must persist in the memory for the lifetime of node. </para><h4>Parameters</h4><dl><dt class="parameter-name">Ch</dt><dd>Character type to use. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_34c55af3504549a475e5b9dfcaa6adf5_134c55af3504549a475e5b9dfcaa6adf5">
|
||||
constructor
|
||||
xml_node::xml_node</h3><h4>Synopsis</h4><code class="synopsis">xml_node(node_type type);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Constructs an empty node with the specified type. Consider using <a href="#classrapidxml_1_1memory__pool" kindref="compound">memory_pool</a> of appropriate document to allocate nodes manually. </para><h4>Parameters</h4><dl><dt class="parameter-name">type</dt><dd class="parameter-def">Type of node to construct. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_975e86937621ae4afe6a423219de30d0_1975e86937621ae4afe6a423219de30d0">function xml_node::type</h3><h4>Synopsis</h4><code class="synopsis">node_type type() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets type of node. </para><h4>Returns</h4>Type of node. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_77aea7d8d996ba4f6bd61cc478a4e72d_177aea7d8d996ba4f6bd61cc478a4e72d">function xml_node::document</h3><h4>Synopsis</h4><code class="synopsis">xml_document<Ch>* document() const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets document of which node is a child. </para><h4>Returns</h4>Pointer to document that contains this node, or 0 if there is no parent document. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_7823e36687669e59c2afdf66334ef35a_17823e36687669e59c2afdf66334ef35a">function xml_node::first_node</h3><h4>Synopsis</h4><code class="synopsis">xml_node<Ch>* first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets first child node, optionally matching node name. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name, in characters, or 0 to have size calculated automatically from string </dd></dl><dl><dt class="parameter-name">case_sensitive</dt><dd class="parameter-def">Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters </dd></dl><h4>Returns</h4>Pointer to found child, or 0 if not found. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_fcb6e2209b591a36d2dadba20d2bc7cc_1fcb6e2209b591a36d2dadba20d2bc7cc">function xml_node::last_node</h3><h4>Synopsis</h4><code class="synopsis">xml_node<Ch>* last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets last child node, optionally matching node name. Behaviour is undefined if node has no children. Use <a href="#classrapidxml_1_1xml__node_7823e36687669e59c2afdf66334ef35a_17823e36687669e59c2afdf66334ef35a" kindref="member">first_node()</a> to test if node has children. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name, in characters, or 0 to have size calculated automatically from string </dd></dl><dl><dt class="parameter-name">case_sensitive</dt><dd class="parameter-def">Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters </dd></dl><h4>Returns</h4>Pointer to found child, or 0 if not found. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_ac2f6886c0107e9d5f156e9542546df6_1ac2f6886c0107e9d5f156e9542546df6">function xml_node::previous_sibling</h3><h4>Synopsis</h4><code class="synopsis">xml_node<Ch>* previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets previous sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use <a href="#classrapidxml_1_1xml__base_798e8df7ea53ade4d9f0701017dce80e_1798e8df7ea53ade4d9f0701017dce80e" kindref="member">parent()</a> to test if node has a parent. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name, in characters, or 0 to have size calculated automatically from string </dd></dl><dl><dt class="parameter-name">case_sensitive</dt><dd class="parameter-def">Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters </dd></dl><h4>Returns</h4>Pointer to found sibling, or 0 if not found. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_b3ead2cefecc03a813836203e3f6f38f_1b3ead2cefecc03a813836203e3f6f38f">function xml_node::next_sibling</h3><h4>Synopsis</h4><code class="synopsis">xml_node<Ch>* next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets next sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use <a href="#classrapidxml_1_1xml__base_798e8df7ea53ade4d9f0701017dce80e_1798e8df7ea53ade4d9f0701017dce80e" kindref="member">parent()</a> to test if node has a parent. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name, in characters, or 0 to have size calculated automatically from string </dd></dl><dl><dt class="parameter-name">case_sensitive</dt><dd class="parameter-def">Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters </dd></dl><h4>Returns</h4>Pointer to found sibling, or 0 if not found. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_5810a09f82f8d53efbe9456286dcec83_15810a09f82f8d53efbe9456286dcec83">function xml_node::first_attribute</h3><h4>Synopsis</h4><code class="synopsis">xml_attribute<Ch>* first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets first attribute of node, optionally matching attribute name. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name, in characters, or 0 to have size calculated automatically from string </dd></dl><dl><dt class="parameter-name">case_sensitive</dt><dd class="parameter-def">Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters </dd></dl><h4>Returns</h4>Pointer to found attribute, or 0 if not found. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_16953d66751b5b949ee4ee2d9c0bc63a_116953d66751b5b949ee4ee2d9c0bc63a">function xml_node::last_attribute</h3><h4>Synopsis</h4><code class="synopsis">xml_attribute<Ch>* last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Gets last attribute of node, optionally matching attribute name. </para><h4>Parameters</h4><dl><dt class="parameter-name">name</dt><dd class="parameter-def">Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero </dd></dl><dl><dt class="parameter-name">name_size</dt><dd class="parameter-def">Size of name, in characters, or 0 to have size calculated automatically from string </dd></dl><dl><dt class="parameter-name">case_sensitive</dt><dd class="parameter-def">Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters </dd></dl><h4>Returns</h4>Pointer to found attribute, or 0 if not found. <p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_a78759bfa429fa2ab6bc5fe617cfa3cf_1a78759bfa429fa2ab6bc5fe617cfa3cf">function xml_node::type</h3><h4>Synopsis</h4><code class="synopsis">void type(node_type type);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Sets type of node. </para><h4>Parameters</h4><dl><dt class="parameter-name">type</dt><dd class="parameter-def">Type of node to set. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_0c39df6617e709eb2fba11300dea63f2_10c39df6617e709eb2fba11300dea63f2">function xml_node::prepend_node</h3><h4>Synopsis</h4><code class="synopsis">void prepend_node(xml_node< Ch > *child);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Prepends a new child node. The prepended child becomes the first child, and all existing children are moved one position back. </para><h4>Parameters</h4><dl><dt class="parameter-name">child</dt><dd class="parameter-def">Node to prepend. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_86de2e22276826089b7baed2599f8dee_186de2e22276826089b7baed2599f8dee">function xml_node::append_node</h3><h4>Synopsis</h4><code class="synopsis">void append_node(xml_node< Ch > *child);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Appends a new child node. The appended child becomes the last child. </para><h4>Parameters</h4><dl><dt class="parameter-name">child</dt><dd class="parameter-def">Node to append. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_780972a57fc447250ab47cc8f421b65e_1780972a57fc447250ab47cc8f421b65e">function xml_node::insert_node</h3><h4>Synopsis</h4><code class="synopsis">void insert_node(xml_node< Ch > *where, xml_node< Ch > *child);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Inserts a new child node at specified place inside the node. All children after and including the specified node are moved one position back. </para><h4>Parameters</h4><dl><dt class="parameter-name">where</dt><dd class="parameter-def">Place where to insert the child, or 0 to insert at the back. </dd></dl><dl><dt class="parameter-name">child</dt><dd class="parameter-def">Node to insert. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_9a31d861e1bddc710839c551a5d2b3a4_19a31d861e1bddc710839c551a5d2b3a4">function xml_node::remove_first_node</h3><h4>Synopsis</h4><code class="synopsis">void remove_first_node();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Removes first child node. If node has no children, behaviour is undefined. Use <a href="#classrapidxml_1_1xml__node_7823e36687669e59c2afdf66334ef35a_17823e36687669e59c2afdf66334ef35a" kindref="member">first_node()</a> to test if node has children. </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_87addf2bc127ee31aa4b5295d3c9b530_187addf2bc127ee31aa4b5295d3c9b530">function xml_node::remove_last_node</h3><h4>Synopsis</h4><code class="synopsis">void remove_last_node();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Removes last child of the node. If node has no children, behaviour is undefined. Use <a href="#classrapidxml_1_1xml__node_7823e36687669e59c2afdf66334ef35a_17823e36687669e59c2afdf66334ef35a" kindref="member">first_node()</a> to test if node has children. </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_9316463a2201631e7e2062b17729f9cd_19316463a2201631e7e2062b17729f9cd">function xml_node::remove_node</h3><h4>Synopsis</h4><code class="synopsis">void remove_node(xml_node< Ch > *where);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Removes specified child from the node. </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_0218147d13e41d5fa60ced4e7a7e9726_10218147d13e41d5fa60ced4e7a7e9726">function xml_node::remove_all_nodes</h3><h4>Synopsis</h4><code class="synopsis">void remove_all_nodes();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Removes all child nodes (but not attributes). </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_f6dffa513da74cc0be71a7ba84f8265e_1f6dffa513da74cc0be71a7ba84f8265e">function xml_node::prepend_attribute</h3><h4>Synopsis</h4><code class="synopsis">void prepend_attribute(xml_attribute< Ch > *attribute);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Prepends a new attribute to the node. </para><h4>Parameters</h4><dl><dt class="parameter-name">attribute</dt><dd class="parameter-def">Attribute to prepend. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_8fbd4f5ef7169d493da9f8d87ac04b77_18fbd4f5ef7169d493da9f8d87ac04b77">function xml_node::append_attribute</h3><h4>Synopsis</h4><code class="synopsis">void append_attribute(xml_attribute< Ch > *attribute);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Appends a new attribute to the node. </para><h4>Parameters</h4><dl><dt class="parameter-name">attribute</dt><dd class="parameter-def">Attribute to append. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_070d5888b0557fe06a5b24961de1b988_1070d5888b0557fe06a5b24961de1b988">function xml_node::insert_attribute</h3><h4>Synopsis</h4><code class="synopsis">void insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Inserts a new attribute at specified place inside the node. All attributes after and including the specified attribute are moved one position back. </para><h4>Parameters</h4><dl><dt class="parameter-name">where</dt><dd class="parameter-def">Place where to insert the attribute, or 0 to insert at the back. </dd></dl><dl><dt class="parameter-name">attribute</dt><dd class="parameter-def">Attribute to insert. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_4eea4a7f6cb484ca9944f7eafe6e1843_14eea4a7f6cb484ca9944f7eafe6e1843">function xml_node::remove_first_attribute</h3><h4>Synopsis</h4><code class="synopsis">void remove_first_attribute();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Removes first attribute of the node. If node has no attributes, behaviour is undefined. Use <a href="#classrapidxml_1_1xml__node_5810a09f82f8d53efbe9456286dcec83_15810a09f82f8d53efbe9456286dcec83" kindref="member">first_attribute()</a> to test if node has attributes. </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_37d87c4d5d89fa0cf05b72ee8d4cba3b_137d87c4d5d89fa0cf05b72ee8d4cba3b">function xml_node::remove_last_attribute</h3><h4>Synopsis</h4><code class="synopsis">void remove_last_attribute();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Removes last attribute of the node. If node has no attributes, behaviour is undefined. Use <a href="#classrapidxml_1_1xml__node_5810a09f82f8d53efbe9456286dcec83_15810a09f82f8d53efbe9456286dcec83" kindref="member">first_attribute()</a> to test if node has attributes. </para><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_c75154db2e768c0e5b541fc8cd0775ab_1c75154db2e768c0e5b541fc8cd0775ab">function xml_node::remove_attribute</h3><h4>Synopsis</h4><code class="synopsis">void remove_attribute(xml_attribute< Ch > *where);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Removes specified attribute from node. </para><h4>Parameters</h4><dl><dt class="parameter-name">where</dt><dd class="parameter-def">Pointer to attribute to be removed. </dd></dl><p/><h3 class="reference-header" id="classrapidxml_1_1xml__node_59e6ad4cfd5e8096c052e71d79561eda_159e6ad4cfd5e8096c052e71d79561eda">function xml_node::remove_all_attributes</h3><h4>Synopsis</h4><code class="synopsis">void remove_all_attributes();
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Removes all attributes of node. </para><p/><h3 class="reference-header" id="namespacerapidxml_6a276b85e2da28c5f9c3dbce61c55682_16a276b85e2da28c5f9c3dbce61c55682">enum node_type</h3><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Enumeration listing all node types produced by the parser. Use <a href="#classrapidxml_1_1xml__node_975e86937621ae4afe6a423219de30d0_1975e86937621ae4afe6a423219de30d0" kindref="member">xml_node::type()</a> function to query node type. </para><h4>Values</h4><dl><dt class="parameter-name">node_document</dt><dd class="parameter-def">A document node. Name and value are empty. </dd></dl><dl><dt class="parameter-name">node_element</dt><dd class="parameter-def">An element node. Name contains element name. Value contains text of first data node. </dd></dl><dl><dt class="parameter-name">node_data</dt><dd class="parameter-def">A data node. Name is empty. Value contains data text. </dd></dl><dl><dt class="parameter-name">node_cdata</dt><dd class="parameter-def">A CDATA node. Name is empty. Value contains data text. </dd></dl><dl><dt class="parameter-name">node_comment</dt><dd class="parameter-def">A comment node. Name is empty. Value contains comment text. </dd></dl><dl><dt class="parameter-name">node_declaration</dt><dd class="parameter-def">A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. </dd></dl><dl><dt class="parameter-name">node_doctype</dt><dd class="parameter-def">A DOCTYPE node. Name is empty. Value contains DOCTYPE text. </dd></dl><dl><dt class="parameter-name">node_pi</dt><dd class="parameter-def">A PI node. Name contains target. Value contains instructions. </dd></dl><p/><h3 class="reference-header" id="namespacerapidxml_ff5d67f74437199d316d2b2660653ae1_1ff5d67f74437199d316d2b2660653ae1">function parse_error_handler</h3><h4>Synopsis</h4><code class="synopsis">void rapidxml::parse_error_handler(const char *what, void *where);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function is called to notify user about the error. It must be defined by the user. <br/><br/>
|
||||
This function cannot return. If it does, the results are undefined. <br/><br/>
|
||||
A very simple definition might look like that: <preformatted>
|
||||
void rapidxml::parse_error_handler(const char *what, void *where)
|
||||
{
|
||||
std::cout << "Parse error: " << what << "\n";
|
||||
std::abort();
|
||||
}
|
||||
</preformatted></para><h4>Parameters</h4><dl><dt class="parameter-name">what</dt><dd class="parameter-def">Human readable description of the error. </dd></dl><dl><dt class="parameter-name">where</dt><dd class="parameter-def">Pointer to character data where error was detected. </dd></dl><p/><h3 class="reference-header" id="namespacerapidxml_b94d570fc4c4ab2423813cd0243326b1_1b94d570fc4c4ab2423813cd0243326b1">function print</h3><h4>Synopsis</h4><code class="synopsis">OutIt rapidxml::print(OutIt out, const xml_node< Ch > &node, int flags=0);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Prints XML to given output iterator. </para><h4>Parameters</h4><dl><dt class="parameter-name">out</dt><dd class="parameter-def">Output iterator to print to. </dd></dl><dl><dt class="parameter-name">node</dt><dd class="parameter-def">Node to be printed. Pass xml_document to print entire document. </dd></dl><dl><dt class="parameter-name">flags</dt><dd class="parameter-def">Flags controlling how XML is printed. </dd></dl><h4>Returns</h4>Output iterator pointing to position immediately after last character of printed text. <p/><h3 class="reference-header" id="namespacerapidxml_13bc37d6d1047acb0efdbc1689221a5e_113bc37d6d1047acb0efdbc1689221a5e">function print</h3><h4>Synopsis</h4><code class="synopsis">std::basic_ostream<Ch>& rapidxml::print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Prints XML to given output stream. </para><h4>Parameters</h4><dl><dt class="parameter-name">out</dt><dd class="parameter-def">Output stream to print to. </dd></dl><dl><dt class="parameter-name">node</dt><dd class="parameter-def">Node to be printed. Pass xml_document to print entire document. </dd></dl><dl><dt class="parameter-name">flags</dt><dd class="parameter-def">Flags controlling how XML is printed. </dd></dl><h4>Returns</h4>Output stream. <p/><h3 class="reference-header" id="namespacerapidxml_5619b38000d967fb223b2b0a8c17463a_15619b38000d967fb223b2b0a8c17463a">function operator<<</h3><h4>Synopsis</h4><code class="synopsis">std::basic_ostream<Ch>& rapidxml::operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node);
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Prints formatted XML to given output stream. Uses default printing flags. Use <a href="#namespacerapidxml_b94d570fc4c4ab2423813cd0243326b1_1b94d570fc4c4ab2423813cd0243326b1" kindref="member">print()</a> function to customize printing process. </para><h4>Parameters</h4><dl><dt class="parameter-name">out</dt><dd class="parameter-def">Output stream to print to. </dd></dl><dl><dt class="parameter-name">node</dt><dd class="parameter-def">Node to be printed. </dd></dl><h4>Returns</h4>Output stream. <p/><h3 class="reference-header" id="namespacerapidxml_87e8bbab53702cf3b438bd553c10b6b9_187e8bbab53702cf3b438bd553c10b6b9">
|
||||
constant
|
||||
parse_no_data_nodes</h3><h4>Synopsis</h4><code class="synopsis">const int parse_no_data_nodes
|
||||
= 0x1;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to not create data nodes. Text of first data node will still be placed in value of parent element, unless <a href="#namespacerapidxml_97e2c4fdc04fae17126f9971a4fc993e_197e2c4fdc04fae17126f9971a4fc993e" kindref="member">rapidxml::parse_no_element_values</a> flag is also specified. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_97e2c4fdc04fae17126f9971a4fc993e_197e2c4fdc04fae17126f9971a4fc993e">
|
||||
constant
|
||||
parse_no_element_values</h3><h4>Synopsis</h4><code class="synopsis">const int parse_no_element_values
|
||||
= 0x2;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to not use text of first data node as a value of parent element. Can be combined with other flags by use of | operator. Note that child data nodes of element node take precendence over its value when printing. That is, if element has one or more child data nodes <i>and</i> a value, the value will be ignored. Use <a href="#namespacerapidxml_87e8bbab53702cf3b438bd553c10b6b9_187e8bbab53702cf3b438bd553c10b6b9" kindref="member">rapidxml::parse_no_data_nodes</a> flag to prevent creation of data nodes if you want to manipulate data using values of elements. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_9cae3801e70437cbc410c24bf6be691c_19cae3801e70437cbc410c24bf6be691c">
|
||||
constant
|
||||
parse_no_string_terminators</h3><h4>Synopsis</h4><code class="synopsis">const int parse_no_string_terminators
|
||||
= 0x4;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to not place zero terminators after strings in the source text. By default zero terminators are placed, modifying source text. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_7223b7815c4fb8b42e6e4e77e1ea6b97_17223b7815c4fb8b42e6e4e77e1ea6b97">
|
||||
constant
|
||||
parse_no_entity_translation</h3><h4>Synopsis</h4><code class="synopsis">const int parse_no_entity_translation
|
||||
= 0x8;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to not translate entities in the source text. By default entities are translated, modifying source text. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_ccde57f6054857ee4042a1b4d98c83b9_1ccde57f6054857ee4042a1b4d98c83b9">
|
||||
constant
|
||||
parse_no_utf8</h3><h4>Synopsis</h4><code class="synopsis">const int parse_no_utf8
|
||||
= 0x10;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. By default, UTF-8 handling is enabled. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_52e2c934ad9c845a5f4cc49570470556_152e2c934ad9c845a5f4cc49570470556">
|
||||
constant
|
||||
parse_declaration_node</h3><h4>Synopsis</h4><code class="synopsis">const int parse_declaration_node
|
||||
= 0x20;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to create XML declaration node. By default, declaration node is not created. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_0f7479dacbc868456d07897a8c072784_10f7479dacbc868456d07897a8c072784">
|
||||
constant
|
||||
parse_comment_nodes</h3><h4>Synopsis</h4><code class="synopsis">const int parse_comment_nodes
|
||||
= 0x40;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to create comments nodes. By default, comment nodes are not created. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_8e187746ba1ca04f107951ad32df962e_18e187746ba1ca04f107951ad32df962e">
|
||||
constant
|
||||
parse_doctype_node</h3><h4>Synopsis</h4><code class="synopsis">const int parse_doctype_node
|
||||
= 0x80;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to create DOCTYPE node. By default, doctype node is not created. Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_1c20b2b2b75711cd76423e119c49f830_11c20b2b2b75711cd76423e119c49f830">
|
||||
constant
|
||||
parse_pi_nodes</h3><h4>Synopsis</h4><code class="synopsis">const int parse_pi_nodes
|
||||
= 0x100;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to create PI nodes. By default, PI nodes are not created. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_a5daff9d61c7d4eaf98e4d42efe628ee_1a5daff9d61c7d4eaf98e4d42efe628ee">
|
||||
constant
|
||||
parse_validate_closing_tags</h3><h4>Synopsis</h4><code class="synopsis">const int parse_validate_closing_tags
|
||||
= 0x200;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to validate closing tag names. If not set, name inside closing tag is irrelevant to the parser. By default, closing tags are not validated. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_ac1f06b1afd47b812732fb521b146fd9_1ac1f06b1afd47b812732fb521b146fd9">
|
||||
constant
|
||||
parse_trim_whitespace</h3><h4>Synopsis</h4><code class="synopsis">const int parse_trim_whitespace
|
||||
= 0x400;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. By default, whitespace is not trimmed. This flag does not cause the parser to modify source text. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_88f95d4e275ba01408fefde83078651b_188f95d4e275ba01408fefde83078651b">
|
||||
constant
|
||||
parse_normalize_whitespace</h3><h4>Synopsis</h4><code class="synopsis">const int parse_normalize_whitespace
|
||||
= 0x800;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. Trimming of leading and trailing whitespace of data is controlled by <a href="#namespacerapidxml_ac1f06b1afd47b812732fb521b146fd9_1ac1f06b1afd47b812732fb521b146fd9" kindref="member">rapidxml::parse_trim_whitespace</a> flag. By default, whitespace is not normalized. If this flag is specified, source text will be modified. Can be combined with other flags by use of | operator. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_45751cf2f38fd6915f35b3122b46d5b6_145751cf2f38fd6915f35b3122b46d5b6">
|
||||
constant
|
||||
parse_default</h3><h4>Synopsis</h4><code class="synopsis">const int parse_default
|
||||
= 0;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Parse flags which represent default behaviour of the parser. This is always equal to 0, so that all other flags can be simply ored together. Normally there is no need to inconveniently disable flags by anding with their negated (~) values. This also means that meaning of each flag is a <i>negation</i> of the default setting. For example, if flag name is <a href="#namespacerapidxml_ccde57f6054857ee4042a1b4d98c83b9_1ccde57f6054857ee4042a1b4d98c83b9" kindref="member">rapidxml::parse_no_utf8</a>, it means that utf-8 is <i>enabled</i> by default, and using the flag will disable it. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_a97ba1a0a79a6d66f4eef3612508d943_1a97ba1a0a79a6d66f4eef3612508d943">
|
||||
constant
|
||||
parse_non_destructive</h3><h4>Synopsis</h4><code class="synopsis">const int parse_non_destructive
|
||||
= parse_no_string_terminators | parse_no_entity_translation;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">A combination of parse flags that forbids any modifications of the source text. This also results in faster parsing. However, note that the following will occur: <ul><li><para>names and values of nodes will not be zero terminated, you have to use <a href="#classrapidxml_1_1xml__base_0dae694c8f7e4d89f1003e2f3a15a43c_10dae694c8f7e4d89f1003e2f3a15a43c" kindref="member">xml_base::name_size()</a> and <a href="#classrapidxml_1_1xml__base_aed5ae791b7164c1ee5e649198cbb3db_1aed5ae791b7164c1ee5e649198cbb3db" kindref="member">xml_base::value_size()</a> functions to determine where name and value ends </para></li><li><para>entities will not be translated </para></li><li><para>whitespace will not be normalized </para></li></ul>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_398c5476e76102f8bd76c10bb0abbe10_1398c5476e76102f8bd76c10bb0abbe10">
|
||||
constant
|
||||
parse_fastest</h3><h4>Synopsis</h4><code class="synopsis">const int parse_fastest
|
||||
= parse_non_destructive | parse_no_data_nodes;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_b4f2515265facb42291570307924bd57_1b4f2515265facb42291570307924bd57">
|
||||
constant
|
||||
parse_full</h3><h4>Synopsis</h4><code class="synopsis">const int parse_full
|
||||
= parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">A combination of parse flags resulting in largest amount of data being extracted. This usually results in slowest parsing. <br/><br/>
|
||||
See <a href="#classrapidxml_1_1xml__document_8338ce6042e7b04d5a42144fb446b69c_18338ce6042e7b04d5a42144fb446b69c" kindref="member">xml_document::parse()</a> function. </para><p/><h3 class="reference-header" id="namespacerapidxml_b08b8d4293c203b69ed6c5ae77ac1907_1b08b8d4293c203b69ed6c5ae77ac1907">
|
||||
constant
|
||||
print_no_indenting</h3><h4>Synopsis</h4><code class="synopsis">const int print_no_indenting
|
||||
= 0x1;
|
||||
</code><h4>Description</h4><para xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Printer flag instructing the printer to suppress indenting of XML. See <a href="#namespacerapidxml_b94d570fc4c4ab2423813cd0243326b1_1b94d570fc4c4ab2423813cd0243326b1" kindref="member">print()</a> function. </para><p/></body></html>
|
||||
+2592
File diff suppressed because it is too large.
Load diff
+174
@@ -0,0 +1,174 @@
|
||||
#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
|
||||
#define RAPIDXML_ITERATORS_HPP_INCLUDED
|
||||
|
||||
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
||||
// Version 1.13
|
||||
// Revision $DateTime: 2009/05/13 01:46:17 $
|
||||
//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
|
||||
|
||||
#include "rapidxml.hpp"
|
||||
|
||||
namespace rapidxml
|
||||
{
|
||||
|
||||
//! Iterator of child nodes of xml_node
|
||||
template<class Ch>
|
||||
class node_iterator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef typename xml_node<Ch> value_type;
|
||||
typedef typename xml_node<Ch> &reference;
|
||||
typedef typename xml_node<Ch> *pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
|
||||
node_iterator()
|
||||
: m_node(0)
|
||||
{
|
||||
}
|
||||
|
||||
node_iterator(xml_node<Ch> *node)
|
||||
: m_node(node->first_node())
|
||||
{
|
||||
}
|
||||
|
||||
reference operator *() const
|
||||
{
|
||||
assert(m_node);
|
||||
return *m_node;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
assert(m_node);
|
||||
return m_node;
|
||||
}
|
||||
|
||||
node_iterator& operator++()
|
||||
{
|
||||
assert(m_node);
|
||||
m_node = m_node->next_sibling();
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_iterator operator++(int)
|
||||
{
|
||||
node_iterator tmp = *this;
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
node_iterator& operator--()
|
||||
{
|
||||
assert(m_node && m_node->previous_sibling());
|
||||
m_node = m_node->previous_sibling();
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_iterator operator--(int)
|
||||
{
|
||||
node_iterator tmp = *this;
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator ==(const node_iterator<Ch> &rhs)
|
||||
{
|
||||
return m_node == rhs.m_node;
|
||||
}
|
||||
|
||||
bool operator !=(const node_iterator<Ch> &rhs)
|
||||
{
|
||||
return m_node != rhs.m_node;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
xml_node<Ch> *m_node;
|
||||
|
||||
};
|
||||
|
||||
//! Iterator of child attributes of xml_node
|
||||
template<class Ch>
|
||||
class attribute_iterator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef typename xml_attribute<Ch> value_type;
|
||||
typedef typename xml_attribute<Ch> &reference;
|
||||
typedef typename xml_attribute<Ch> *pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
|
||||
attribute_iterator()
|
||||
: m_attribute(0)
|
||||
{
|
||||
}
|
||||
|
||||
attribute_iterator(xml_node<Ch> *node)
|
||||
: m_attribute(node->first_attribute())
|
||||
{
|
||||
}
|
||||
|
||||
reference operator *() const
|
||||
{
|
||||
assert(m_attribute);
|
||||
return *m_attribute;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
assert(m_attribute);
|
||||
return m_attribute;
|
||||
}
|
||||
|
||||
attribute_iterator& operator++()
|
||||
{
|
||||
assert(m_attribute);
|
||||
m_attribute = m_attribute->next_attribute();
|
||||
return *this;
|
||||
}
|
||||
|
||||
attribute_iterator operator++(int)
|
||||
{
|
||||
attribute_iterator tmp = *this;
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
attribute_iterator& operator--()
|
||||
{
|
||||
assert(m_attribute && m_attribute->previous_attribute());
|
||||
m_attribute = m_attribute->previous_attribute();
|
||||
return *this;
|
||||
}
|
||||
|
||||
attribute_iterator operator--(int)
|
||||
{
|
||||
attribute_iterator tmp = *this;
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator ==(const attribute_iterator<Ch> &rhs)
|
||||
{
|
||||
return m_attribute == rhs.m_attribute;
|
||||
}
|
||||
|
||||
bool operator !=(const attribute_iterator<Ch> &rhs)
|
||||
{
|
||||
return m_attribute != rhs.m_attribute;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
xml_attribute<Ch> *m_attribute;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+428
@@ -0,0 +1,428 @@
|
||||
#ifndef RAPIDXML_PRINT_HPP_INCLUDED
|
||||
#define RAPIDXML_PRINT_HPP_INCLUDED
|
||||
|
||||
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
||||
// Version 1.13
|
||||
// Revision $DateTime: 2009/05/13 01:46:17 $
|
||||
//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
|
||||
|
||||
#include "rapidxml.hpp"
|
||||
|
||||
// Only include streams if not disabled
|
||||
#ifndef RAPIDXML_NO_STREAMS
|
||||
#include <ostream>
|
||||
#include <iterator>
|
||||
#endif
|
||||
|
||||
namespace rapidxml
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Printing flags
|
||||
|
||||
const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Internal
|
||||
|
||||
//! \cond internal
|
||||
namespace internal
|
||||
{
|
||||
|
||||
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Internal character operations
|
||||
|
||||
// Copy characters from given range to given output iterator
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
|
||||
{
|
||||
while (begin != end)
|
||||
*out++ = *begin++;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Copy characters from given range to given output iterator and expand
|
||||
// characters into references (< > ' " &)
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
if (*begin == noexpand)
|
||||
{
|
||||
*out++ = *begin; // No expansion, copy character
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (*begin)
|
||||
{
|
||||
case Ch('<'):
|
||||
*out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
|
||||
break;
|
||||
case Ch('>'):
|
||||
*out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
|
||||
break;
|
||||
case Ch('\''):
|
||||
*out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
|
||||
break;
|
||||
case Ch('"'):
|
||||
*out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
|
||||
break;
|
||||
case Ch('&'):
|
||||
*out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
|
||||
break;
|
||||
default:
|
||||
*out++ = *begin; // No expansion, copy character
|
||||
}
|
||||
}
|
||||
++begin; // Step to next character
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Fill given output iterator with repetitions of the same character
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt fill_chars(OutIt out, int n, Ch ch)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
*out++ = ch;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Find character
|
||||
template<class Ch, Ch ch>
|
||||
inline bool find_char(const Ch *begin, const Ch *end)
|
||||
{
|
||||
while (begin != end)
|
||||
if (*begin++ == ch)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Print children of the node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
|
||||
out = print_node(out, child, flags, indent);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print attributes of the node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
|
||||
{
|
||||
for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
|
||||
{
|
||||
if (attribute->name() && attribute->value())
|
||||
{
|
||||
// Print attribute name
|
||||
*out = Ch(' '), ++out;
|
||||
out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
|
||||
*out = Ch('='), ++out;
|
||||
// Print attribute value using appropriate quote type
|
||||
if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
|
||||
{
|
||||
*out = Ch('\''), ++out;
|
||||
out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
|
||||
*out = Ch('\''), ++out;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out = Ch('"'), ++out;
|
||||
out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
|
||||
*out = Ch('"'), ++out;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print data node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_data);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print data node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_cdata);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'); ++out;
|
||||
*out = Ch('!'); ++out;
|
||||
*out = Ch('['); ++out;
|
||||
*out = Ch('C'); ++out;
|
||||
*out = Ch('D'); ++out;
|
||||
*out = Ch('A'); ++out;
|
||||
*out = Ch('T'); ++out;
|
||||
*out = Ch('A'); ++out;
|
||||
*out = Ch('['); ++out;
|
||||
out = copy_chars(node->value(), node->value() + node->value_size(), out);
|
||||
*out = Ch(']'); ++out;
|
||||
*out = Ch(']'); ++out;
|
||||
*out = Ch('>'); ++out;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print element node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_element);
|
||||
|
||||
// Print element name and attributes, if any
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
out = copy_chars(node->name(), node->name() + node->name_size(), out);
|
||||
out = print_attributes(out, node, flags);
|
||||
|
||||
// If node is childless
|
||||
if (node->value_size() == 0 && !node->first_node())
|
||||
{
|
||||
// Print childless node tag ending
|
||||
*out = Ch('/'), ++out;
|
||||
*out = Ch('>'), ++out;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Print normal node tag ending
|
||||
*out = Ch('>'), ++out;
|
||||
|
||||
// Test if node contains a single data node only (and no other nodes)
|
||||
xml_node<Ch> *child = node->first_node();
|
||||
if (!child)
|
||||
{
|
||||
// If node has no children, only print its value without indenting
|
||||
out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
|
||||
}
|
||||
else if (child->next_sibling() == 0 && child->type() == node_data)
|
||||
{
|
||||
// If node has a sole data child, only print its value without indenting
|
||||
out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Print all children with full indenting
|
||||
if (!(flags & print_no_indenting))
|
||||
*out = Ch('\n'), ++out;
|
||||
out = print_children(out, node, flags, indent + 1);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
}
|
||||
|
||||
// Print node end
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('/'), ++out;
|
||||
out = copy_chars(node->name(), node->name() + node->name_size(), out);
|
||||
*out = Ch('>'), ++out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// Print declaration node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
// Print declaration start
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('?'), ++out;
|
||||
*out = Ch('x'), ++out;
|
||||
*out = Ch('m'), ++out;
|
||||
*out = Ch('l'), ++out;
|
||||
|
||||
// Print attributes
|
||||
out = print_attributes(out, node, flags);
|
||||
|
||||
// Print declaration end
|
||||
*out = Ch('?'), ++out;
|
||||
*out = Ch('>'), ++out;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print comment node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_comment);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('!'), ++out;
|
||||
*out = Ch('-'), ++out;
|
||||
*out = Ch('-'), ++out;
|
||||
out = copy_chars(node->value(), node->value() + node->value_size(), out);
|
||||
*out = Ch('-'), ++out;
|
||||
*out = Ch('-'), ++out;
|
||||
*out = Ch('>'), ++out;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print doctype node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_doctype);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('!'), ++out;
|
||||
*out = Ch('D'), ++out;
|
||||
*out = Ch('O'), ++out;
|
||||
*out = Ch('C'), ++out;
|
||||
*out = Ch('T'), ++out;
|
||||
*out = Ch('Y'), ++out;
|
||||
*out = Ch('P'), ++out;
|
||||
*out = Ch('E'), ++out;
|
||||
*out = Ch(' '), ++out;
|
||||
out = copy_chars(node->value(), node->value() + node->value_size(), out);
|
||||
*out = Ch('>'), ++out;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print pi node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_pi);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('?'), ++out;
|
||||
out = copy_chars(node->name(), node->name() + node->name_size(), out);
|
||||
*out = Ch(' '), ++out;
|
||||
out = copy_chars(node->value(), node->value() + node->value_size(), out);
|
||||
*out = Ch('?'), ++out;
|
||||
*out = Ch('>'), ++out;
|
||||
return out;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Internal printing operations
|
||||
|
||||
// Print node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
// Print proper node type
|
||||
switch (node->type())
|
||||
{
|
||||
|
||||
// Document
|
||||
case node_document:
|
||||
out = print_children(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Element
|
||||
case node_element:
|
||||
out = print_element_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Data
|
||||
case node_data:
|
||||
out = print_data_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// CDATA
|
||||
case node_cdata:
|
||||
out = print_cdata_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Declaration
|
||||
case node_declaration:
|
||||
out = print_declaration_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Comment
|
||||
case node_comment:
|
||||
out = print_comment_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Doctype
|
||||
case node_doctype:
|
||||
out = print_doctype_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Pi
|
||||
case node_pi:
|
||||
out = print_pi_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Unknown
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// If indenting not disabled, add line break after node
|
||||
if (!(flags & print_no_indenting))
|
||||
*out = Ch('\n'), ++out;
|
||||
|
||||
// Return modified iterator
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
//! \endcond
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Printing
|
||||
|
||||
//! Prints XML to given output iterator.
|
||||
//! \param out Output iterator to print to.
|
||||
//! \param node Node to be printed. Pass xml_document to print entire document.
|
||||
//! \param flags Flags controlling how XML is printed.
|
||||
//! \return Output iterator pointing to position immediately after last character of printed text.
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
|
||||
{
|
||||
return internal::print_node(out, &node, flags, 0);
|
||||
}
|
||||
|
||||
#ifndef RAPIDXML_NO_STREAMS
|
||||
|
||||
//! Prints XML to given output stream.
|
||||
//! \param out Output stream to print to.
|
||||
//! \param node Node to be printed. Pass xml_document to print entire document.
|
||||
//! \param flags Flags controlling how XML is printed.
|
||||
//! \return Output stream.
|
||||
template<class Ch>
|
||||
inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
|
||||
{
|
||||
print(std::ostream_iterator<Ch>(out), node, flags);
|
||||
return out;
|
||||
}
|
||||
|
||||
//! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
|
||||
//! \param out Output stream to print to.
|
||||
//! \param node Node to be printed.
|
||||
//! \return Output stream.
|
||||
template<class Ch>
|
||||
inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
|
||||
{
|
||||
return print(out, node);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
#ifndef RAPIDXML_UTILS_HPP_INCLUDED
|
||||
#define RAPIDXML_UTILS_HPP_INCLUDED
|
||||
|
||||
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
||||
// Version 1.13
|
||||
// Revision $DateTime: 2009/05/13 01:46:17 $
|
||||
//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
|
||||
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
|
||||
|
||||
#include "rapidxml.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace rapidxml
|
||||
{
|
||||
|
||||
//! Represents data loaded from a file
|
||||
template<class Ch = char>
|
||||
class file
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Loads file into the memory. Data will be automatically destroyed by the destructor.
|
||||
//! \param filename Filename to load.
|
||||
file(const char *filename)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// Open stream
|
||||
basic_ifstream<Ch> stream(filename, ios::binary);
|
||||
if (!stream)
|
||||
throw runtime_error(string("cannot open file ") + filename);
|
||||
stream.unsetf(ios::skipws);
|
||||
|
||||
// Determine stream size
|
||||
stream.seekg(0, ios::end);
|
||||
size_t size = stream.tellg();
|
||||
stream.seekg(0);
|
||||
|
||||
// Load data and add terminating 0
|
||||
m_data.resize(size + 1);
|
||||
stream.read(&m_data.front(), static_cast<streamsize>(size));
|
||||
m_data[size] = 0;
|
||||
}
|
||||
|
||||
//! Loads file into the memory. Data will be automatically destroyed by the destructor
|
||||
//! \param stream Stream to load from
|
||||
file(std::basic_istream<Ch> &stream)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// Load data and add terminating 0
|
||||
stream.unsetf(ios::skipws);
|
||||
m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
|
||||
if (stream.fail() || stream.bad())
|
||||
throw runtime_error("error reading stream");
|
||||
m_data.push_back(0);
|
||||
}
|
||||
|
||||
//! Gets file data.
|
||||
//! \return Pointer to data of file.
|
||||
Ch *data()
|
||||
{
|
||||
return &m_data.front();
|
||||
}
|
||||
|
||||
//! Gets file data.
|
||||
//! \return Pointer to data of file.
|
||||
const Ch *data() const
|
||||
{
|
||||
return &m_data.front();
|
||||
}
|
||||
|
||||
//! Gets file data size.
|
||||
//! \return Size of file data, in characters.
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<Ch> m_data; // File data
|
||||
|
||||
};
|
||||
|
||||
//! Counts children of node. Time complexity is O(n).
|
||||
//! \return Number of children of node
|
||||
template<class Ch>
|
||||
inline std::size_t count_children(xml_node<Ch> *node)
|
||||
{
|
||||
xml_node<Ch> *child = node->first_node();
|
||||
std::size_t count = 0;
|
||||
while (child)
|
||||
{
|
||||
++count;
|
||||
child = child->next_sibling();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//! Counts attributes of node. Time complexity is O(n).
|
||||
//! \return Number of attributes of node
|
||||
template<class Ch>
|
||||
inline std::size_t count_attributes(xml_node<Ch> *node)
|
||||
{
|
||||
xml_attribute<Ch> *attr = node->first_attribute();
|
||||
std::size_t count = 0;
|
||||
while (attr)
|
||||
{
|
||||
++count;
|
||||
attr = attr->next_attribute();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+2845
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,482 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/entityid.h>
|
||||
#include <osg/BoundingBox>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Geode>
|
||||
#include <dtEntity/message.h>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QPolygonF>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include "viewerinterface.h"
|
||||
#include "cameraviewposition.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace dtEntity
|
||||
{
|
||||
class EntityManager;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class IconComponent;
|
||||
class TextComponent;
|
||||
class ViewWidget;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct OBB
|
||||
{
|
||||
osg::Matrix mMatrix;
|
||||
osg::Matrix mMatrixInverse;
|
||||
osg::BoundingBox mBB;
|
||||
QPolygonF mPoly;
|
||||
dtEntity::StringId mBuilding = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct BuildingData
|
||||
{
|
||||
std::string mDescription;
|
||||
std::string mDisplayName;
|
||||
std::string mFeatureId;
|
||||
std::string mFileName;
|
||||
std::string mBuildingXMLPath;
|
||||
double mX = 0;
|
||||
double mY = 0;
|
||||
double mZ = 0;
|
||||
double mOrientation = 0;
|
||||
int mBuildingGroup = 0;
|
||||
bool properlySpawned = false;
|
||||
bool roomBBoxedLoaded = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct BuildingLevel
|
||||
{
|
||||
// entity id of visible entity in building view
|
||||
dtEntity::EntityId mEntityId;
|
||||
|
||||
// floorId of xml file (-1 for floor_-1; 2 for floor_2...)
|
||||
int mFloorId;
|
||||
|
||||
// height of lowest walkable area in level above building origin
|
||||
float mHeightAboveGround;
|
||||
|
||||
// transforms from building local space to level local space
|
||||
osg::Matrix mLocalToLevel;
|
||||
|
||||
// bounding box of level in world space (untransformed by view mode)
|
||||
osg::BoundingBox mBounds;
|
||||
|
||||
BuildingLevel(dtEntity::EntityId eid, int floorId, float h, const osg::BoundingBox &bb)
|
||||
: mEntityId(eid), mFloorId(floorId), mHeightAboveGround(h), mBounds(bb)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct PlayerPosition
|
||||
{
|
||||
osg::Vec2d mPosition;
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct PlayerDisplay
|
||||
{
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
dtEntity::EntityId mLocalPlayerId = 0;
|
||||
IconComponent *mIcon = nullptr;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct Device
|
||||
{
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
std::string mPath;
|
||||
osg::Vec3d mPosition;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct DeviceDisplay
|
||||
{
|
||||
Device *mDevice = nullptr;
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
dtEntity::EntityId mLocalPlayerId = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct Name
|
||||
{
|
||||
dtEntity::EntityId mWorldPlayerId;
|
||||
std::string mtext;
|
||||
std::string mdistext;
|
||||
std::string mbuilding;
|
||||
osg::Vec3d mPosition;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct NameDisplay
|
||||
{
|
||||
Name* mName = nullptr;
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
dtEntity::EntityId mLocalPlayerId = 0;
|
||||
bool visible = false;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class Shot
|
||||
{
|
||||
public:
|
||||
Shot(const int32_t id,
|
||||
const osg::Vec3d& shooterPos,
|
||||
const osg::Vec3d& targetPos,
|
||||
int buildingIdSrc,
|
||||
int rommNumberSrc,
|
||||
int buildingIdDst,
|
||||
int rommNumberDst,
|
||||
int lineType,
|
||||
const osg::Vec4& color,
|
||||
unsigned int duration_s,
|
||||
unsigned int durationMax_s,
|
||||
double simTimeCreated) :
|
||||
mId(id)
|
||||
, mShooterPos(shooterPos)
|
||||
, mTargetPos(targetPos)
|
||||
, mBuildingIdSrc(buildingIdSrc)
|
||||
, mRoomNumberSrc(rommNumberSrc)
|
||||
, mBuildingIdDst(buildingIdDst)
|
||||
, mRoomNumberDst(rommNumberDst)
|
||||
, mLineType(lineType)
|
||||
, mColor(color)
|
||||
, mDuration_s(duration_s)
|
||||
, m_DurationMax_s(durationMax_s)
|
||||
, mSimTimeCreated(simTimeCreated) {
|
||||
|
||||
}
|
||||
|
||||
void setDisplayTime(unsigned int duration_s) {
|
||||
if(duration_s > m_DurationMax_s)
|
||||
m_DurationMax_s = duration_s;
|
||||
mDuration_s = duration_s;
|
||||
}
|
||||
double simTimeCreated() const {
|
||||
return mSimTimeCreated;
|
||||
}
|
||||
|
||||
double displayTime() const {
|
||||
return mSimTimeCreated + mDuration_s;
|
||||
}
|
||||
|
||||
double lifeTime() const {
|
||||
return mSimTimeCreated + (m_DurationMax_s*2);
|
||||
}
|
||||
|
||||
const osg::Vec3d& getShooterPos() const { return mShooterPos; }
|
||||
const osg::Vec3d& getTargetPos() const { return mTargetPos; }
|
||||
int getBuildingIdSrc() const { return mBuildingIdSrc; }
|
||||
double getSimeTimeCreated() const { return mSimTimeCreated; }
|
||||
int getRoomNumberSrc() const { return mRoomNumberSrc; }
|
||||
int getBuildingIdDst() const { return mBuildingIdDst; }
|
||||
int getRoomNumberDst() const { return mRoomNumberDst; }
|
||||
int getDuration() const { return mDuration_s; }
|
||||
int getLineType() const { return mLineType; }
|
||||
|
||||
const osg::Vec4& getColor() const { return mColor; }
|
||||
int32_t getId() const { return mId; }
|
||||
|
||||
private:
|
||||
int32_t mId;
|
||||
osg::Vec3d mShooterPos;
|
||||
osg::Vec3d mTargetPos;
|
||||
int mBuildingIdSrc;
|
||||
int mRoomNumberSrc;
|
||||
int mBuildingIdDst;
|
||||
int mRoomNumberDst;
|
||||
int mLineType;
|
||||
osg::Vec4 mColor;
|
||||
unsigned int mDuration_s, m_DurationMax_s;
|
||||
double mSimTimeCreated;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct ShotDisplay
|
||||
{
|
||||
Shot *mShot = nullptr;
|
||||
osg::ref_ptr<osg::Geode> mGeode;
|
||||
};
|
||||
|
||||
// fwd decl
|
||||
struct Building;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief The BuildingDisplay struct
|
||||
|
||||
class OrthoMotionModelComponent;
|
||||
|
||||
struct BuildingDisplay
|
||||
{
|
||||
// context id of this display
|
||||
unsigned int mContextId = 0;
|
||||
|
||||
// local entity holding building data
|
||||
dtEntity::EntityId mAttachPointId = 0;
|
||||
|
||||
// all levels in building
|
||||
std::vector<BuildingLevel> mLevels;
|
||||
|
||||
// combined bounding box of all levels of building without viewmode transformation
|
||||
osg::BoundingBox mWorldBounds;
|
||||
|
||||
// combined bounding box of all levels of building with viewmode transformation
|
||||
osg::BoundingBox mLocalBounds;
|
||||
|
||||
// entity id of camera entity
|
||||
dtEntity::EntityId mCameraId = 0;
|
||||
|
||||
// entity id of orthomotionmodel entity
|
||||
dtEntity::EntityId mMotionModelId = 0;
|
||||
OrthoMotionModelComponent *pMotion = nullptr;
|
||||
|
||||
// entity id of light source entity
|
||||
dtEntity::EntityId mLightId = 0;
|
||||
|
||||
// display players as dots or as icons?
|
||||
PlayerDisplayMode mPlayerDisplayMode = PlayerDisplayMode::Icons;
|
||||
|
||||
// how are the buildings projected?
|
||||
ViewMode mViewMode = ViewMode::ISOMETRIC;
|
||||
|
||||
// all players currently displayed in this building
|
||||
std::vector<PlayerDisplay> mPlayers;
|
||||
|
||||
// shoot lines currently displayed
|
||||
std::vector<ShotDisplay> mShotDisplays;
|
||||
|
||||
// all players currently displayed in this building
|
||||
std::vector<DeviceDisplay> mDeviceDisplays;
|
||||
|
||||
// all names currently displayed in this building
|
||||
std::vector<NameDisplay> mNameDisplays;
|
||||
|
||||
// should camera rotation be locked to global map rotation?
|
||||
bool mLockRotation = false;
|
||||
|
||||
// are the roomNames shown?
|
||||
bool mNameMode = false;
|
||||
|
||||
// how are the shoot Lines displayed?
|
||||
bool mLineMode = false;
|
||||
|
||||
BuildingDisplay() = default;
|
||||
|
||||
BuildingDisplay(unsigned int contextid, ViewMode vm)
|
||||
: mContextId(contextid)
|
||||
, mViewMode(vm)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct Building
|
||||
{
|
||||
// building entity in world space
|
||||
dtEntity::EntityId mWorldBuildingId = 0;
|
||||
|
||||
// all currently open displays of this building
|
||||
std::vector<BuildingDisplay> mDisplays;
|
||||
|
||||
// transformation of building in world space
|
||||
osg::Matrix mWorldToLocal;
|
||||
|
||||
// transformation of building in world space
|
||||
osg::Matrix mLocalToWorld;
|
||||
|
||||
// used for assigning walking entities to buildings
|
||||
std::string mNavMeshGrpName;
|
||||
|
||||
// stores shot data
|
||||
std::vector<Shot *> mShots;
|
||||
|
||||
// stores device data
|
||||
std::vector<Device *> mDevices;
|
||||
|
||||
// Building Display Name
|
||||
std::string mBuildingDisplayName;
|
||||
|
||||
// stores name data
|
||||
std::vector<Name*> mNames;
|
||||
|
||||
// the corresponding feature id from the xml file
|
||||
std::string mFeatureId;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class BuildingManager
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
explicit BuildingManager(dtEntity::EntityManager &em);
|
||||
~BuildingManager();
|
||||
|
||||
void addBuilding(dtEntity::EntityId buildingid, const std::string &featureId);
|
||||
void deleteAllBuildings();
|
||||
|
||||
BuildingDisplay *getBuildingDisplay(unsigned int contextid);
|
||||
void applyViewModeToBuildingParts(const Building &bldg, BuildingDisplay &dspl) const;
|
||||
|
||||
bool displayBuilding(const std::string& featureId, unsigned int contextid, dtEntity::EntityId buildingid, const osg::Vec4 &bgcolor, ViewMode viewmode, bool exactPos);
|
||||
bool displayBuilding(unsigned int contextid, dtEntity::EntityId buildingid, const osg::Vec4 &bgcolor, ViewMode viewmode, bool exactPos);
|
||||
|
||||
bool setCameraPosition(unsigned int contextid, const BuildingViewer::CameraViewPosition& pos);
|
||||
bool getCameraPosition(unsigned int contextid, BuildingViewer::CameraViewPosition& pos);
|
||||
bool setDefaultCameraPosition(unsigned int contextid);
|
||||
|
||||
void closeBuildingDisplay(unsigned int contextid);
|
||||
void changeViewMode(unsigned int contextId, ViewMode viewmode, bool useOriginViewPos = true);
|
||||
void changeLineMode(unsigned int contextId, bool line);
|
||||
void changeNameMode(unsigned int contextId, bool name);
|
||||
|
||||
void applyMapRotation(const Building &bd, BuildingDisplay &dspl);
|
||||
void lockViewRotationToMapRotation(unsigned int contextId, bool lock);
|
||||
void setPlayerDisplayMode(unsigned int contextId, PlayerDisplayMode mode);
|
||||
void setWallTransparency(unsigned int contextId, float value);
|
||||
|
||||
float getMapRotation() const;
|
||||
void setMapRotation(float angle);
|
||||
|
||||
void openOverview(unsigned int contextid);
|
||||
|
||||
void addPlayerToBuildings(const std::string &navmeshgrpname, dtEntity::EntityId eid,
|
||||
const osg::Vec4 &color, const std::string &symbol,
|
||||
const osg::Vec3d &pos, bool visible);
|
||||
void removePlayerFromBuilding(const std::string &navmeshgrpname, dtEntity::EntityId eid, const std::string &roomname);
|
||||
void updatePlayerPosition(const std::string &navmeshgrpname, dtEntity::EntityId eid,
|
||||
const osg::Vec3d &pos, int roomNumber);
|
||||
|
||||
osg::Vec3d remapPosition(const Building &bd, const BuildingDisplay &dspl, const osg::Vec3d &world, int roomNumber = -1);
|
||||
|
||||
void setPlayerColor(dtEntity::EntityId eid, const osg::Vec4 &color);
|
||||
void setPlayerIcon(dtEntity::EntityId eid, const std::string &path);
|
||||
void reloadPlayerIcons();
|
||||
void updatePlayerPartyColor(dtEntity::EntityId eid, const VCtrl::Color& col);
|
||||
void setShowPlayerSelection(dtEntity::EntityId eid, bool show);
|
||||
void setShowDisplayNamesSelection(dtEntity::EntityId eid, bool show);
|
||||
void setShowHidePlayer(dtEntity::EntityId eid, bool show);
|
||||
void setShowHideDisplayNames(dtEntity::EntityId eid, unsigned int contextId, bool show);
|
||||
void setRoomDestructionValue(dtEntity::EntityId eid, const std::string &roomname, float value);
|
||||
void setBuildingDestructionValue(dtEntity::EntityId eid, float value);
|
||||
void setBuildingDisplayName(const std::string& featureId, dtEntity::EntityId eid, const std::string& strDisplayName);
|
||||
void setBuildingDisplayName(dtEntity::EntityId eid, const std::string& strDisplayName);
|
||||
void setRoomDisplayName(const std::string& featureId, dtEntity::EntityId eid, const std::string& roomname, const std::string& strDisplayName);
|
||||
void setRoomDisplayName(Building *building, const std::string &roomname, const std::string& strDisplayName);
|
||||
|
||||
void removeShoot(int32_t id);
|
||||
void showShoot(int32_t id, dtEntity::EntityId shooter, dtEntity::EntityId target,
|
||||
const dtEntity::Vec3d &shooterPos, const dtEntity::Vec3d &targetPos, int buildingIdSrc, int roomNumberSrc,
|
||||
int buildingIdDst, int roomNumberDst, int lineType, float duration, double simTimeCreated);
|
||||
|
||||
dtEntity::EntityId getWorldPlayerIdFromLocalPlayer(dtEntity::EntityId local) const;
|
||||
dtEntity::EntityId getWorldNameIdFromLocalName(dtEntity::EntityId local, std::string &buildingName, std::string &room) const;
|
||||
|
||||
void addDeviceToBuilding(dtEntity::EntityId iconmainid, dtEntity::EntityId buildingid,
|
||||
const osg::Vec3d &pos, const std::string &iconpath);
|
||||
void removeDeviceFromBuilding(dtEntity::EntityId iconmainid);
|
||||
|
||||
|
||||
// Load building XML and add room OBBs to tree
|
||||
bool AddRoomOBBs(const BuildingData &);
|
||||
const std::map<std::string, VCtrl::OBB> &GetRoomOBBs() const { return mRooms; }
|
||||
|
||||
// Look up room OBB, return true if room exists
|
||||
bool getRoomBounds(const std::string &bldgname, const std::string &roomname, VCtrl::OBB &obb) const;
|
||||
|
||||
|
||||
bool LoadBuildings(const std::string &path, std::vector<BuildingData> &);
|
||||
|
||||
size_t getNumBuildings() const;
|
||||
void getBuildingIds(std::vector<dtEntity::EntityId> &toFill) const;
|
||||
dtEntity::EntityId getNextBuilding(const osg::Vec3d &pos, float &distance, std::string &featureId) const;
|
||||
Building getBuildingFromFeatureId(const std::string &bldname) const;
|
||||
|
||||
// all players currently in this room
|
||||
using RoomPlayers = std::vector<PlayerPosition>;
|
||||
// add player to room
|
||||
osg::Vec2d AddRoomUsages(const std::string& bldgname, const std::string& roomname, VCtrl::PlayerPosition& playPos);
|
||||
const std::map<std::string, RoomPlayers> &GetRoomUsages() const { return mUsedRooms; }
|
||||
// delete player in room
|
||||
void deleteRoomUsagePlayer(const std::string& bldgname, const std::string& roomname, dtEntity::EntityId playerId);
|
||||
void SetExactPos(bool exactPos) { mExactPos = exactPos; }
|
||||
bool GetExactPos() const { return mExactPos; }
|
||||
void updateShotDuration(unsigned int newDuration_s);
|
||||
using CallbackCamPosChanged = std::function<void(unsigned int, const BuildingViewer::CameraViewPosition &)>;
|
||||
void setCallbackCamPosChanged(const CallbackCamPosChanged &cb);
|
||||
|
||||
private:
|
||||
void updateShots(const Building &bd, BuildingDisplay &dspl);
|
||||
void updateDevices(const Building &bd, BuildingDisplay &dspl);
|
||||
void createRoomNames(dtEntity::EntityId buildingid, Building& building);
|
||||
void updateNames(const Building& bd, BuildingDisplay& dspl);
|
||||
void repositionCamera(const Building &bd, const BuildingDisplay &dspl, bool useOriginViewPos = true);
|
||||
void updatePlayerPositions(const Building &bd, BuildingDisplay &dspl);
|
||||
void addPlayerToBuilding(const Building &bd, BuildingDisplay &dspl, dtEntity::EntityId eid,
|
||||
const osg::Vec4 &color, const std::string &symbol, const osg::Vec3d &pos,
|
||||
bool visible);
|
||||
static osg::Vec2d shiftPosition(const VCtrl::OBB& obb, const osg::Vec2d& pos, double& shiftValue);
|
||||
void cameraViewPositionChanged(unsigned int contextId, const BuildingViewer::CameraViewPosition &viewPos);
|
||||
|
||||
std::set<unsigned int> m_setInitialCameraPositionSet; // If an context ID of a building is included in this set the initial camera position had been set
|
||||
|
||||
std::map<std::string, std::map<std::string, std::string>> m_mapBuildingRoomNames; // Maps a building feature id (not the dtEntity::EntityId!) to the building's room names
|
||||
std::map<std::string, std::string> m_mapBuildingDisplayNames; // key = feature id value = BuildingDisplayName
|
||||
dtEntity::EntityManager *mEntityManager;
|
||||
|
||||
std::vector<Building *> mBuildings;
|
||||
QMutex m_mutexShots;
|
||||
|
||||
bool mShotOverview;
|
||||
bool mExactPos;
|
||||
float mMapRotation;
|
||||
dtEntity::MessageFunctor mTickFunctor;
|
||||
|
||||
void Tick(const dtEntity::Message &message);
|
||||
|
||||
std::map<std::string, VCtrl::OBB> mRooms;
|
||||
std::map<std::string, RoomPlayers> mUsedRooms;
|
||||
CallbackCamPosChanged mCbCamPosChanged;
|
||||
|
||||
// NLDEVCTRL-495
|
||||
// Die Positionierung der a) TeilnehmerSymbole, b) RaumBezeichner und c) Trefferlinien der Kanalisation ist problembehaftet.
|
||||
// Bei Raum 027 und 028 der Kanalisation wurde der RaumBezeichner nicht im unteren Level, sondern im darüberliegenden Level dargestellt.
|
||||
// Level entspricht den floors/Ebenen in der Standard-Darstellung isometric, also in "gespreizter" Darstellung.
|
||||
// Als Ursache hat sich Ansatz in BuildingManager::remapPosition() herausgestellt. Beim Remapping wird versucht, die aktuelle Position aufgrund des z-Wertes einem Floor/Level zuzuordnen. Wenn die Gebäude waagerechte Floors haben, funktioniert dies sehr gut.
|
||||
// Die Kanalisation weist aber im linken Bereich (Raum 027 und 028) einen Anstieg auf. Betritt also ein Teilnehmer einen der Räume, so wird aufgrund seines z-Wertes die darüberliegenden Etage ermittelt und der Tln "zu hoch" angezeigt.
|
||||
// Lösung:
|
||||
// Beim Einlesen der Struktur-XML-Datei wird ein Lookup-Table erstellt. mRoomToFloorPerBldg stellt dann zu jedem Raum den Floor zur Verfügung.
|
||||
// Bei Positionsmeldungen wird Bldg/Room durchgereicht, sodass es beim Remapping einbezogen werden kann.
|
||||
// Bei der Darstellung der RaumBezeichner verhält es sich analog.
|
||||
// Bei den Trefferlinien beinhaltet das DDS-Topic HitLineInfo den Information Bldg/Room nur für den Getroffenen. Daher wird die Peilspitze der Trefferlinien korrekt dargestellt.
|
||||
// ToDo:
|
||||
// Der Ursprung der Trefferlinien wird nach wie vor durch Analyse des z-Wertes vorgenommen -> Probleme bei Raum 027, 028.
|
||||
// Wahrscheinlich müsst im SVC PPM (ParticipantHandlerForExercise::createHitlineInfo) nixcht nur die OriginatorPosition, sondern ggf. auch Bldg/Room in das DDS-Topic HitLineInfo eingetragen werden.
|
||||
// Wahrscheinlich wegen dem Replay eine DB-Änderung notwendig.
|
||||
bool getFloorOfRoom(const std::string &bdlgFeatureId, int roomNumber, int &floorOut) const;
|
||||
// <bldg , <roomNumber, floor>
|
||||
// <featureId, <roomNumber, floor>
|
||||
std::map<std::string, std::map<int,int> > mRoomToFloorPerBldg;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
struct CameraViewPosition
|
||||
{
|
||||
CameraViewPosition() = default;
|
||||
CameraViewPosition(double left, double right, double bottom, double top)
|
||||
: m_left(left), m_right(right), m_bottom(bottom), m_top(top)
|
||||
{}
|
||||
|
||||
double m_left = 0;
|
||||
double m_right = 0;
|
||||
double m_bottom = 0;
|
||||
double m_top = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#if defined VIEWER_CTRL_LIBRARY_STATIC
|
||||
# define VIEWER_CTRL_EXPORT
|
||||
#else
|
||||
# if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
|
||||
# ifdef VIEWER_CTRL_LIBRARY
|
||||
# define VIEWER_CTRL_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define VIEWER_CTRL_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# ifdef VIEWER_CTRL_LIBRARY
|
||||
# define VIEWER_CTRL_EXPORT __attribute__ ((visibility("default")))
|
||||
# else
|
||||
# define VIEWER_CTRL_EXPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# pragma warning (disable: 4251)
|
||||
# pragma warning(disable : 4355) // 'this' used in initializer list
|
||||
#endif
|
||||
@@ -0,0 +1,349 @@
|
||||
#include "iconcomponent.h"
|
||||
|
||||
|
||||
#include <dtEntity/nodemasks.h>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/LineWidth>
|
||||
#include <osg/Node>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/Texture2D>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <sstream>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId IconComponent::TYPE(dtEntity::SID("Icon"));
|
||||
const dtEntity::StringId IconComponent::PathId(dtEntity::SID("Path"));
|
||||
const dtEntity::StringId IconComponent::VOffsetId(dtEntity::SID("VOffset"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
IconComponent::IconComponent()
|
||||
: dtEntityOSG::TransformComponent(new osg::AutoTransform())
|
||||
, mPath(
|
||||
dtEntity::DynamicStringProperty::SetValueCB(this, &IconComponent::SetPath),
|
||||
dtEntity:: DynamicStringProperty::GetValueCB(this, &IconComponent::GetPath)
|
||||
)
|
||||
, mVOffset(
|
||||
dtEntity::DynamicFloatProperty::SetValueCB(this, &IconComponent::SetVOffset),
|
||||
dtEntity:: DynamicFloatProperty::GetValueCB(this, &IconComponent::GetVOffset)
|
||||
)
|
||||
{
|
||||
Register(PathId, &mPath);
|
||||
Register(VOffsetId, &mVOffset);
|
||||
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->setName("icon");
|
||||
tr->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
|
||||
tr->setAutoScaleToScreen(true);
|
||||
tr->setNodeMask(dtEntity::NodeMasks::PICKABLE | dtEntity::NodeMasks::VISIBLE);
|
||||
tr->setNormal(osg::Vec3(0, 1, 0));
|
||||
osg::StateSet *ss = tr->getOrCreateStateSet();
|
||||
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
ss->setRenderBinDetails(90, "DepthSortedBin");
|
||||
ss->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
osg::ref_ptr<osg::LineWidth> lw = new osg::LineWidth();
|
||||
lw->setWidth(2);
|
||||
ss->setAttributeAndModes(lw, osg::StateAttribute::ON);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::Rebuild()
|
||||
{
|
||||
#define DOT_RADIUS 5
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->dirtyBound();
|
||||
tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 10));
|
||||
tr->removeChildren(0, tr->getNumChildren());
|
||||
|
||||
if (!mVisible) return;
|
||||
|
||||
osg::ref_ptr<osg::Geode> g = new osg::Geode();
|
||||
tr->addChild(g);
|
||||
tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 1));
|
||||
|
||||
int x, y, w, h;
|
||||
if (mShowDot)
|
||||
{
|
||||
x = y = -DOT_RADIUS * 2;
|
||||
w = h = DOT_RADIUS * 4;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> circle = new osg::Geometry();
|
||||
osg::Vec4Array *colours = new osg::Vec4Array(1);
|
||||
(*colours)[0] = mColor;
|
||||
circle->setColorArray(colours);
|
||||
circle->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
const unsigned int n_points = 16;
|
||||
osg::Vec3Array *coords = new osg::Vec3Array(n_points + 2);
|
||||
(*coords)[0] = osg::Vec3(0, 0, 0);
|
||||
const double dx = 2.0 * osg::PI / n_points;
|
||||
|
||||
for (unsigned int j = 1; j < n_points + 2; ++j)
|
||||
(*coords)[j].set(osg::Vec3(cos(dx * j) * DOT_RADIUS, sin(dx * j) * DOT_RADIUS, 0));
|
||||
circle->setVertexArray(coords);
|
||||
circle->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN, 0, n_points + 2));
|
||||
g->addDrawable(circle);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::ref_ptr<osg::Image> img = osgDB::readImageFile(mPathVal);
|
||||
if (img.valid())
|
||||
{
|
||||
int b = 4;
|
||||
g->addDrawable(IconSystem::CreateSquare(img->s(), img->t(), mVOffsetVal, mOriginAtBottom, img));
|
||||
if (mOriginAtBottom)
|
||||
{
|
||||
x = -img->s() / 2 - b;
|
||||
y = 0 - b;
|
||||
w = img->s() + b * 2;
|
||||
h = img->t() + b * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = -img->s() / 2 - b;
|
||||
y = -img->t() / 2 - b;
|
||||
w = img->s() + b * 2;
|
||||
h = img->t() + b * 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Could not read symbol from path '" << mPathVal<< "'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSelected)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> sel = new osg::Geometry();
|
||||
g->addDrawable(sel);
|
||||
osg::Vec4Array *colours = new osg::Vec4Array(1);
|
||||
(*colours)[0] = osg::Vec4(1, 0, 0, 1);
|
||||
sel->setColorArray(colours);
|
||||
sel->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
osg::Vec3Array *coords = new osg::Vec3Array(4);
|
||||
(*coords)[0] = osg::Vec3(x , y , 0);
|
||||
(*coords)[1] = osg::Vec3(x , y + h, 0);
|
||||
(*coords)[2] = osg::Vec3(x + w, y + h, 0);
|
||||
(*coords)[3] = osg::Vec3(x + w, y , 0);
|
||||
sel->setVertexArray(coords);
|
||||
sel->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, 4));
|
||||
osg::ref_ptr<osg::PolygonMode> p = new osg::PolygonMode;
|
||||
p->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
|
||||
sel->getOrCreateStateSet()->setAttribute(p);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string IconComponent::GetPath() const
|
||||
{
|
||||
return mPathVal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetPath(const std::string &path)
|
||||
{
|
||||
mPathVal = path;
|
||||
Rebuild();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::Reload()
|
||||
{
|
||||
if(mPathVal.size())
|
||||
{
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
float IconComponent::GetVOffset() const
|
||||
{
|
||||
return mVOffsetVal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetVOffset(float v)
|
||||
{
|
||||
if (mVOffsetVal != v)
|
||||
{
|
||||
mVOffsetVal = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Vec3d IconComponent::GetTranslation() const
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
return tr->getPosition();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetTranslation(const dtEntity::Vec3d &v)
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->setPosition(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Vec3d IconComponent::GetScale() const
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
return tr->getScale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetScale(const dtEntity::Vec3d &v)
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->setScale(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Quat IconComponent::GetRotation() const
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
return tr->getRotation();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetRotation(const dtEntity::Quat &v)
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->setRotation(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetColor(const osg::Vec4 &v)
|
||||
{
|
||||
if (mColor != v)
|
||||
{
|
||||
mColor = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetShowDot(bool v)
|
||||
{
|
||||
if (mShowDot != v)
|
||||
{
|
||||
mShowDot = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetOriginAtBottom(bool v)
|
||||
{
|
||||
if (mOriginAtBottom != v)
|
||||
{
|
||||
mOriginAtBottom = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool IconComponent::GetShowSelection() const
|
||||
{
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetShowSelection(bool v)
|
||||
{
|
||||
if (mSelected != v)
|
||||
{
|
||||
mSelected = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetVisible(bool v)
|
||||
{
|
||||
if (mVisible != v)
|
||||
{
|
||||
mVisible = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetRoomNumber(int roomNumber)
|
||||
{
|
||||
mRoomNumber = roomNumber;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
IconSystem::IconSystem(dtEntity::EntityManager &em)
|
||||
: dtEntity::DefaultEntitySystem<IconComponent>(em, dtEntityOSG::TransformComponent::TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
osg::Drawable *IconSystem::CreateSquare(float width, float height, float voffset, bool originAtBottom, osg::Image *image)
|
||||
{
|
||||
// set up the Geometry.
|
||||
osg::Geometry *geom = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array *coords = new osg::Vec3Array(4);
|
||||
if (originAtBottom)
|
||||
{
|
||||
(*coords)[0] = osg::Vec3(-width / 2.0f, voffset, 0);
|
||||
(*coords)[1] = osg::Vec3(width / 2.0f, voffset, 0);
|
||||
(*coords)[2] = osg::Vec3(width / 2.0f, voffset + height, 0);
|
||||
(*coords)[3] = osg::Vec3(-width / 2.0f, voffset + height, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*coords)[0] = osg::Vec3(-width / 2.0f, voffset - height / 2, 0);
|
||||
(*coords)[1] = osg::Vec3(width / 2.0f, voffset - height / 2, 0);
|
||||
(*coords)[2] = osg::Vec3(width / 2.0f, voffset + height / 2, 0);
|
||||
(*coords)[3] = osg::Vec3(-width / 2.0f, voffset + height / 2, 0);
|
||||
}
|
||||
|
||||
geom->setVertexArray(coords);
|
||||
|
||||
osg::Vec3Array *norms = new osg::Vec3Array(1);
|
||||
(*norms)[0] = osg::Vec3(0, 1, 0);
|
||||
|
||||
geom->setNormalArray(norms);
|
||||
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::Vec4Array *colours = new osg::Vec4Array(1);
|
||||
(*colours)[0] = osg::Vec4(1, 1, 1, 1);
|
||||
geom->setColorArray(colours);
|
||||
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::Vec2Array *tcoords = new osg::Vec2Array(4);
|
||||
(*tcoords)[0].set(0.0f, 0.0f);
|
||||
(*tcoords)[1].set(1.0f, 0.0f);
|
||||
(*tcoords)[2].set(1.0f, 1.0f);
|
||||
(*tcoords)[3].set(0.0f, 1.0f);
|
||||
geom->setTexCoordArray(0, tcoords);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
|
||||
|
||||
if (image)
|
||||
{
|
||||
osg::StateSet *stateset = geom->getOrCreateStateSet();
|
||||
osg::Texture2D *texture = new osg::Texture2D;
|
||||
texture->setResizeNonPowerOfTwoHint(false);
|
||||
texture->setImage(image);
|
||||
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
return geom;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntityOSG/nodecomponent.h>
|
||||
#include <osg/AutoTransform>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class IconComponent : public dtEntityOSG::TransformComponent
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
static const dtEntity::StringId PathId;
|
||||
static const dtEntity::StringId VOffsetId;
|
||||
|
||||
|
||||
IconComponent();
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return ((id == TYPE));
|
||||
}
|
||||
|
||||
std::string GetPath() const;
|
||||
void SetPath(const std::string &path);
|
||||
void Reload();
|
||||
|
||||
float GetVOffset() const;
|
||||
void SetVOffset(float v);
|
||||
|
||||
osg::Vec4 GetColor() const { return mColor; }
|
||||
void SetColor(const osg::Vec4 &);
|
||||
|
||||
bool GetShowDot() const { return mShowDot; }
|
||||
void SetShowDot(bool);
|
||||
|
||||
bool GetOriginAtBottom() const { return mOriginAtBottom; }
|
||||
void SetOriginAtBottom(bool);
|
||||
|
||||
dtEntity::Vec3d GetTranslation() const override;
|
||||
void SetTranslation(const dtEntity::Vec3d &) override;
|
||||
|
||||
dtEntity::Vec3d GetScale() const override;
|
||||
void SetScale(const dtEntity::Vec3d &) override;
|
||||
|
||||
dtEntity::Quat GetRotation() const override;
|
||||
void SetRotation(const dtEntity::Quat &) override;
|
||||
|
||||
bool GetShowSelection() const;
|
||||
void SetShowSelection(bool v);
|
||||
|
||||
void SetVisible(bool v);
|
||||
bool GetVisible() const { return mVisible; }
|
||||
|
||||
void SetRoomNumber(int roomNumber);
|
||||
int GetRoomNumber() const { return mRoomNumber; }
|
||||
|
||||
private:
|
||||
|
||||
void Rebuild();
|
||||
|
||||
dtEntity::DynamicStringProperty mPath;
|
||||
dtEntity::DynamicFloatProperty mVOffset;
|
||||
|
||||
std::string mPathVal;
|
||||
osg::Vec4 mColor;
|
||||
float mVOffsetVal = 0;
|
||||
bool mShowDot = false;
|
||||
bool mOriginAtBottom = false;
|
||||
bool mSelected = false;
|
||||
bool mVisible = false;
|
||||
|
||||
int mRoomNumber{-1};
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
// iterates over MovementComponents and updates the translation of the entity
|
||||
// after applying forces
|
||||
class IconSystem final : public dtEntity::DefaultEntitySystem<IconComponent>
|
||||
{
|
||||
|
||||
public:
|
||||
explicit IconSystem(dtEntity::EntityManager &em);
|
||||
|
||||
static osg::Drawable *CreateSquare(float width, float height, float voffset, bool originAtBottom, osg::Image *image = nullptr);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
#include "mainloop.h"
|
||||
|
||||
#include "iconcomponent.h"
|
||||
#include "modelsplittercomponent.h"
|
||||
#include "motionmodel.h"
|
||||
#include "orthomotionmodel.h"
|
||||
#include "playercomponent.h"
|
||||
#include "roomdestructioncomponent.h"
|
||||
#include "textcomponent.h"
|
||||
#include "viewerinterfaceimpl.h"
|
||||
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/init.h>
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/profile.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/systeminterface.h>
|
||||
#include <dtEntity/entitymanager.h>
|
||||
#include <dtEntityOSG/initosgviewer.h>
|
||||
#include <dtEntityOSG/layerattachpointcomponent.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/lightcomponent.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include <dtEntityOSG/osgsysteminterface.h>
|
||||
#include <dtEntityOSG/osgwindowinterface.h>
|
||||
#include <dtEntityOSG/osgdebugdrawinterface.h>
|
||||
#include <dtEntityOSG/osginputinterface.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#ifdef BUILD_WITH_GSTREAMER
|
||||
#include "videocomponent.h"
|
||||
#endif
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class MyReadFileCallback : public osgDB::Registry::ReadFileCallback
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string &fileName, const osgDB::ReaderWriter::Options *options)
|
||||
{
|
||||
osgDB::ReaderWriter::ReadResult res = osgDB::Registry::instance()->readNodeImplementation(fileName, options);
|
||||
if (res.notFound() || res.notHandled() || res.error())
|
||||
{
|
||||
LOG_DEBUG("DatabasePager could not load file, stopped trying: " << fileName);
|
||||
return osgDB::ReaderWriter::ReadResult(nullptr, osgDB::ReaderWriter::ReadResult::FILE_LOADED);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class MainLoop::Impl
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
osg::ref_ptr<osgViewer::CompositeViewer> mViewer;
|
||||
CtrlImpl *mInterface = nullptr;
|
||||
dtEntityOSG::OSGSystemInterface *mSysIf = nullptr;
|
||||
dtEntityOSG::OSGInputInterface *mInputIf = nullptr;
|
||||
dtEntity::EntityManager *mEntityManager;
|
||||
osg::Timer_t mStartFrameTick = 0;
|
||||
dtEntity::Timer_t mSimulationClockTime = 0;
|
||||
bool mProfilingEnabled = false;
|
||||
|
||||
Impl()
|
||||
: mEntityManager(new dtEntity::EntityManager)
|
||||
{
|
||||
dtEntity::MessageFunctor f(this, &MainLoop::Impl::onFastForward);
|
||||
mEntityManager->RegisterForMessages(dtEntity::SID("FastForwardMessage"), f);
|
||||
|
||||
dtEntity::MessageFunctor s(this, &MainLoop::Impl::onEntitySelected);
|
||||
mEntityManager->RegisterForMessages(dtEntity::RequestEntitySelectMessage::TYPE, s);
|
||||
|
||||
dtEntity::MessageFunctor s2(this, &MainLoop::Impl::onEntityDeselected);
|
||||
mEntityManager->RegisterForMessages(dtEntity::RequestEntityDeselectMessage::TYPE, s2);
|
||||
}
|
||||
|
||||
~Impl()
|
||||
{
|
||||
delete mEntityManager;
|
||||
delete mSysIf;
|
||||
delete mInputIf;
|
||||
delete mInterface;
|
||||
}
|
||||
|
||||
// react to fast forward message by
|
||||
void onFastForward(const dtEntity::Message &msg)
|
||||
{
|
||||
// TODO Test!
|
||||
double endtime = msg.GetDouble(dtEntity::SID("EndTime"));
|
||||
|
||||
while (mInterface->GetSimulationTime() < endtime)
|
||||
{
|
||||
constexpr auto step = 0.5;
|
||||
double t = mInterface->GetSimulationTime() + step;
|
||||
mSimulationClockTime += step / osg::Timer::instance()->getSecondsPerTick();
|
||||
mInterface->SetSimulationTime(t);
|
||||
mSysIf->SetTimeValues(t, step, step, mSimulationClockTime);
|
||||
mViewer->advance(t);
|
||||
mViewer->eventTraversal();
|
||||
mSysIf->EmitTickMessagesAndQueuedMessages();
|
||||
mViewer->updateTraversal();
|
||||
mSysIf->EmitPostUpdateMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// translate RequestEntitySelectMessage to EntityDeselectedMessage
|
||||
// (normally this would be handled by a selection manager, but
|
||||
// selection in this viewer is so simple that it is not necessary
|
||||
// to have real selection management)
|
||||
void onEntitySelected(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::RequestEntitySelectMessage &msg =
|
||||
static_cast<const dtEntity::RequestEntitySelectMessage &>(m);
|
||||
dtEntity::EntitySelectedMessage mo;
|
||||
mo.SetAboutEntityId(msg.GetAboutEntityId());
|
||||
mEntityManager->EmitMessage(mo);
|
||||
}
|
||||
|
||||
// translate RequestEntityDeselectMessage to EntityDeselectedMessage
|
||||
void onEntityDeselected(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::RequestEntityDeselectMessage &msg =
|
||||
static_cast<const dtEntity::RequestEntityDeselectMessage &>(m);
|
||||
dtEntity::EntityDeselectedMessage mo;
|
||||
mo.SetAboutEntityId(msg.GetAboutEntityId());
|
||||
mEntityManager->EmitMessage(mo);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
MainLoop::MainLoop(int argc, char **argv, QWidget *parentWidget)
|
||||
: mImpl(new Impl)
|
||||
{
|
||||
osgDB::Registry::instance()->setReadFileCallback(new MyReadFileCallback());
|
||||
|
||||
assert(!mImpl->mViewer.valid());
|
||||
|
||||
//////////////////////////// Setup OSG Viewer /////////////////////////
|
||||
// osg arguments parser wants to modify argc, argv
|
||||
{
|
||||
int argc_cpy = argc;
|
||||
std::vector<char *> argv_cpy;
|
||||
argv_cpy.reserve(argc);
|
||||
for (int i = 0; i < argc; ++i)
|
||||
argv_cpy.push_back(argv[i]);
|
||||
osg::ArgumentParser args(&argc_cpy, argv_cpy.data());
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_putenv_s("OSG_RUN_FRAME_SCHEME", "ON_DEMAND");
|
||||
#else
|
||||
setenv("OSG_RUN_FRAME_SCHEME", "ON_DEMAND", 1);
|
||||
#endif
|
||||
// turn on antialiasing
|
||||
osg::DisplaySettings::instance()->setNumMultiSamples(4);
|
||||
osg::DisplaySettings::instance()->setDepthBuffer(true);
|
||||
|
||||
|
||||
mImpl->mViewer = new osgViewer::CompositeViewer(args);
|
||||
// Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different
|
||||
// thread" when the viewer is run multi-threaded, this is regression from Qt4
|
||||
mImpl->mViewer->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
|
||||
|
||||
// don't exit on escape
|
||||
mImpl->mViewer->setKeyEventSetsDone(0);
|
||||
|
||||
//mImpl->mViewer->setEndBarrierPosition(osgViewer::ViewerBase::BeforeSwapBuffers);
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
dtEntity::LogManager::GetInstance().AddListener(new dtEntity::ConsoleLogHandler());
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////// setup dtEntity -> OSG interfaces ////////////////////////
|
||||
{
|
||||
mImpl->mSysIf = new dtEntityOSG::OSGSystemInterface(mImpl->mEntityManager->GetMessagePump(), argc, (const char **)argv);
|
||||
mImpl->mInputIf = new dtEntityOSG::OSGInputInterface(mImpl->mEntityManager->GetMessagePump());
|
||||
// give application system access to viewer
|
||||
mImpl->mSysIf->SetViewer(mImpl->mViewer);
|
||||
dtEntity::SetSystemInterface(mImpl->mSysIf);
|
||||
dtEntity::SetInputInterface(mImpl->mInputIf);
|
||||
dtEntity::SetWindowInterface(new dtEntityOSG::OSGWindowInterface(*mImpl->mEntityManager));
|
||||
|
||||
dtEntity::SetupDataPaths(argc, argv, false);
|
||||
}
|
||||
|
||||
|
||||
dtEntity::EntityManager &em = *mImpl->mEntityManager;
|
||||
|
||||
//////////////////////////// Add entity systems /////////////////////////
|
||||
{
|
||||
// this is a required component system, so add it immediately
|
||||
em.AddEntitySystem(*new dtEntity::MapSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::LayerSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::CameraSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::PositionAttitudeTransformSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::StaticMeshSystem(em));
|
||||
em.AddEntitySystem(*new RoomDestructionSystem(em));
|
||||
em.AddEntitySystem(*new MotionModelSystem(em));
|
||||
em.AddEntitySystem(*new ModelSplitterSystem(em));
|
||||
em.AddEntitySystem(*new OrthoMotionModelSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::LightSystem(em));
|
||||
em.AddEntitySystem(*new PlayerSystem(em));
|
||||
em.AddEntitySystem(*new IconSystem(em));
|
||||
em.AddEntitySystem(*new TextSystem(em));
|
||||
#ifdef BUILD_WITH_GSTREAMER
|
||||
em.AddEntitySystem(*new VideoSystem(em));
|
||||
#endif
|
||||
|
||||
dtEntityOSG::LayerAttachPointSystem *layerattach = new dtEntityOSG::LayerAttachPointSystem(em);
|
||||
em.AddEntitySystem(*layerattach);
|
||||
layerattach->CreateSceneGraphRootEntity(new osg::Group());
|
||||
|
||||
mImpl->mInterface = new CtrlImpl(em, parentWidget);
|
||||
|
||||
// need layer system for debug draw interface, so set it up now
|
||||
dtEntity::SetDebugDrawInterface(new dtEntityOSG::OSGDebugDrawInterface(em));
|
||||
}
|
||||
|
||||
//////////////////////////// Init time tracking /////////////////////////
|
||||
{
|
||||
mImpl->mStartFrameTick = osg::Timer::instance()->tick();
|
||||
mImpl->mInterface->SetSimulationTime(0);
|
||||
time_t t;
|
||||
time(&t);
|
||||
mImpl->mSimulationClockTime = t / osg::Timer::instance()->getSecondsPerTick();
|
||||
}
|
||||
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string curArgv = argv[i];
|
||||
if (!curArgv.empty() && curArgv == "--openOverview")
|
||||
mImpl->mInterface->OpenOverview();
|
||||
}
|
||||
|
||||
//////////////////////////// Start simulation /////////////////////////
|
||||
{
|
||||
dtEntity::StartSystemMessage msg;
|
||||
em.EnqueueMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
MainLoop::~MainLoop()
|
||||
{
|
||||
delete mImpl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::EntityManager *MainLoop::getEntityManager() const
|
||||
{
|
||||
return mImpl->mEntityManager;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ViewerInterface *MainLoop::getViewerInterface() const
|
||||
{
|
||||
return mImpl->mInterface;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool MainLoop::getProfilingEnabled() const
|
||||
{
|
||||
return mImpl->mProfilingEnabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::setProfilingEnabled(bool v)
|
||||
{
|
||||
mImpl->mProfilingEnabled = v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::tick()
|
||||
{
|
||||
dtEntityOSG::OSGSystemInterface *iface = dtEntityOSG::GetOSGSystemInterface();
|
||||
|
||||
if (!mImpl->mInterface->allViewWindowsExposed())
|
||||
return;
|
||||
|
||||
if (getViewerInterface()->GetNonRealtimeMode())
|
||||
{
|
||||
float deltaTime = 1.0f / mImpl->mInterface->GetFrameRate();
|
||||
float deltaSimTime = deltaTime;
|
||||
mImpl->mSimulationClockTime += deltaSimTime / osg::Timer::instance()->getSecondsPerTick();
|
||||
mImpl->mInterface->SetSimulationTime(mImpl->mInterface->GetSimulationTime() + deltaSimTime);
|
||||
iface->SetTimeValues(mImpl->mInterface->GetSimulationTime(), deltaSimTime, deltaTime, mImpl->mSimulationClockTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
float deltaTime = 0;
|
||||
float deltaSimTime = 0;
|
||||
|
||||
dtEntity::Timer_t tick = osg::Timer::instance()->tick();
|
||||
deltaTime = static_cast<float>(osg::Timer::instance()->delta_s(mImpl->mStartFrameTick, tick));
|
||||
deltaSimTime = deltaTime * mImpl->mInterface->GetTimeScale();
|
||||
mImpl->mStartFrameTick = tick;
|
||||
|
||||
mImpl->mSimulationClockTime += deltaSimTime / osg::Timer::instance()->getSecondsPerTick();
|
||||
mImpl->mInterface->SetSimulationTime(mImpl->mInterface->GetSimulationTime() + deltaSimTime);
|
||||
iface->SetTimeValues(mImpl->mInterface->GetSimulationTime(), deltaSimTime, deltaTime, mImpl->mSimulationClockTime);
|
||||
}
|
||||
|
||||
if (mImpl->mProfilingEnabled)
|
||||
{
|
||||
|
||||
static dtEntity::StringId frameId = dtEntity::SID("Frame");
|
||||
static dtEntity::StringId frameAdvanceId = dtEntity::SID("Frame_Advance");
|
||||
static dtEntity::StringId frameEvTrId = dtEntity::SID("Frame_EventTraversal");
|
||||
static dtEntity::StringId frameUpTrId = dtEntity::SID("Frame_UpdateTraversal");
|
||||
static dtEntity::StringId frameRenderTrId = dtEntity::SID("Frame_RenderingTraversals");
|
||||
|
||||
static unsigned int framecount = 0;
|
||||
|
||||
CProfileManager::Increment_Frame_Counter();
|
||||
|
||||
CProfileManager::Start_Profile(frameId);
|
||||
|
||||
CProfileManager::Start_Profile(frameAdvanceId);
|
||||
mImpl->mViewer->advance();
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
CProfileManager::Start_Profile(frameEvTrId);
|
||||
mImpl->mViewer->eventTraversal();
|
||||
iface->EmitTickMessagesAndQueuedMessages();
|
||||
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
if (mImpl->mViewer->getNumViews() > 0 && mImpl->mViewer->checkNeedToDoFrame())
|
||||
{
|
||||
CProfileManager::Start_Profile(frameUpTrId);
|
||||
mImpl->mViewer->updateTraversal();
|
||||
iface->EmitPostUpdateMessage();
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
CProfileManager::Start_Profile(frameRenderTrId);
|
||||
mImpl->mViewer->renderingTraversals();
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
else
|
||||
iface->EmitPostUpdateMessage();
|
||||
|
||||
CProfileManager::Stop_Profile(); // frameId
|
||||
|
||||
if (++framecount > 99)
|
||||
{
|
||||
CProfileManager::dumpAll();
|
||||
fflush(stdout);
|
||||
framecount = 0;
|
||||
CProfileManager::Reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
NASTY BUG WORKAROUND:
|
||||
Somehow, changes made to the frame are not immediately shown when
|
||||
a new frame is requested. This only happens when more than one view is opened.
|
||||
The workaround is to render again two more times even if no frame redraw
|
||||
was requested.
|
||||
*/
|
||||
static int renderagaincnt = 0;
|
||||
|
||||
mImpl->mViewer->advance(DBL_MAX);
|
||||
mImpl->mViewer->eventTraversal();
|
||||
iface->EmitTickMessagesAndQueuedMessages();
|
||||
bool needFrame = mImpl->mViewer->checkNeedToDoFrame();
|
||||
if (mImpl->mViewer->getNumViews() > 0 && (renderagaincnt != 0 || needFrame))
|
||||
{
|
||||
if (mImpl->mViewer->getNumViews() == 1)
|
||||
renderagaincnt = 0;
|
||||
else if (needFrame)
|
||||
renderagaincnt = 2;
|
||||
else
|
||||
--renderagaincnt;
|
||||
|
||||
mImpl->mViewer->updateTraversal();
|
||||
iface->EmitPostUpdateMessage();
|
||||
mImpl->mViewer->renderingTraversals();
|
||||
}
|
||||
else
|
||||
iface->EmitPostUpdateMessage();
|
||||
}
|
||||
|
||||
if (!getViewerInterface()->GetNonRealtimeMode() && mImpl->mViewer->getRunMaxFrameRate() > 0.0)
|
||||
{
|
||||
if (mImpl->mProfilingEnabled)
|
||||
{
|
||||
static dtEntity::StringId sleepId = dtEntity::SID("Frame_Sleep");
|
||||
CProfileManager::Start_Profile(sleepId);
|
||||
}
|
||||
osg::Timer_t endFrameTick = osg::Timer::instance()->tick();
|
||||
double frameTime =
|
||||
osg::Timer::instance()->delta_s(mImpl->mStartFrameTick, endFrameTick);
|
||||
|
||||
double minFrameTime = 1.0 / mImpl->mViewer->getRunMaxFrameRate();
|
||||
if (frameTime < minFrameTime)
|
||||
OpenThreads::Thread::microSleep(1000000.0 * (minFrameTime - frameTime));
|
||||
if (mImpl->mProfilingEnabled)
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::GetCurrentPosition(Vec3d &position, Vec3d &lookAt)
|
||||
{
|
||||
position = Vec3d();
|
||||
lookAt = Vec3d();
|
||||
dtEntity::MapSystem *ms;
|
||||
mImpl->mEntityManager->GetES(ms);
|
||||
if (!ms)
|
||||
return;
|
||||
dtEntity::EntityId eid = ms->GetEntityIdByUniqueId("cam_overview");
|
||||
dtEntityOSG::CameraComponent *camcomp;
|
||||
if (!mImpl->mEntityManager->GetComponent(eid, camcomp))
|
||||
{
|
||||
LOG_ERROR("GetCurrentPosition: Error accessing camera");
|
||||
return;
|
||||
}
|
||||
|
||||
osg::Vec3d p = camcomp->GetPosition();
|
||||
osg::Vec3d la = camcomp->GetEyeDirection() + camcomp->GetPosition();
|
||||
position.x = p[0]; position.y = p[1]; position.z = p[2];
|
||||
lookAt.x = la[0]; lookAt.y = la[1]; lookAt.z = la[2];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "export.h"
|
||||
|
||||
class QWidget;
|
||||
namespace dtEntity
|
||||
{
|
||||
class EntityManager;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class ViewerInterface;
|
||||
struct Vec3d;
|
||||
|
||||
class VIEWER_CTRL_EXPORT MainLoop
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
MainLoop(int argc, char **argv, QWidget *parentWidget);
|
||||
~MainLoop();
|
||||
|
||||
dtEntity::EntityManager *getEntityManager() const;
|
||||
ViewerInterface *getViewerInterface() const;
|
||||
|
||||
bool getProfilingEnabled() const;
|
||||
void setProfilingEnabled(bool v);
|
||||
|
||||
void shutDown();
|
||||
bool isRunning() const;
|
||||
|
||||
void tick();
|
||||
void GetCurrentPosition(Vec3d &position, Vec3d &lookAt);
|
||||
private:
|
||||
|
||||
class Impl;
|
||||
Impl *mImpl;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "messages.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RegisterMessageTypes(dtEntity::MessageFactory& em)
|
||||
{
|
||||
em.RegisterMessageType<NavMeshGroupChangedMessage>(NavMeshGroupChangedMessage::TYPE);
|
||||
em.RegisterMessageType<TransformSendMessage>(TransformSendMessage::TYPE);
|
||||
em.RegisterMessageType<PlayerPickedMessage>(PlayerPickedMessage::TYPE);
|
||||
em.RegisterMessageType<DisplayNameClickedMessage>(DisplayNameClickedMessage::TYPE);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType NavMeshGroupChangedMessage::TYPE(dtEntity::SID("NavMeshGroupChangedMessage"));
|
||||
const dtEntity::StringId NavMeshGroupChangedMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId NavMeshGroupChangedMessage::GroupNameId(dtEntity::SID("GroupName"));
|
||||
const dtEntity::StringId NavMeshGroupChangedMessage::PreviousGroupNameId(dtEntity::SID("PreviousGroupName"));
|
||||
|
||||
NavMeshGroupChangedMessage::NavMeshGroupChangedMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(AboutEntityId, &mAboutEntity);
|
||||
this->Register(GroupNameId, &mGroupName);
|
||||
this->Register(PreviousGroupNameId, &mPreviousGroupName);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType TransformSendMessage::TYPE(dtEntity::SID("TransformSendMessage"));
|
||||
const dtEntity::StringId TransformSendMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId TransformSendMessage::PositionId(dtEntity::SID("Position"));
|
||||
const dtEntity::StringId TransformSendMessage::AttitudeId(dtEntity::SID("Attitude"));
|
||||
const dtEntity::StringId TransformSendMessage::RoomNumberId(dtEntity::SID("RoomNumber"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TransformSendMessage::TransformSendMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
Register(AboutEntityId, &mAboutEntity);
|
||||
Register(PositionId, &mPosition);
|
||||
Register(AttitudeId, &mAttitude);
|
||||
Register(RoomNumberId, &mRoomNumber);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType PlayerPickedMessage::TYPE(dtEntity::SID("PlayerPickedMessage"));
|
||||
const dtEntity::StringId PlayerPickedMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId PlayerPickedMessage::PositionId(dtEntity::SID("Position"));
|
||||
|
||||
|
||||
PlayerPickedMessage::PlayerPickedMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(AboutEntityId, &mAboutEntity);
|
||||
this->Register(PositionId, &mPosition);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType FastForwardMessage::TYPE(dtEntity::SID("FastForwardMessage"));
|
||||
const dtEntity::StringId FastForwardMessage::EndTimeId(dtEntity::SID("EndTime"));
|
||||
|
||||
FastForwardMessage::FastForwardMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(EndTimeId, &mEndTime);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType HideSelectionMessage::TYPE(dtEntity::SID("HideSelectionMessage"));
|
||||
const dtEntity::StringId HideSelectionMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId HideSelectionMessage::NameFlagId(dtEntity::SID("NameFlag"));
|
||||
|
||||
HideSelectionMessage::HideSelectionMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(AboutEntityId, &mAboutEntity);
|
||||
this->Register(NameFlagId, &mNameFlag);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType RemoveShootMessage::TYPE(dtEntity::SID("RemoveShootMessage"));
|
||||
|
||||
RemoveShootMessage::RemoveShootMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType ShootMessage::TYPE(dtEntity::SID("ShootMessage"));
|
||||
|
||||
ShootMessage::ShootMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType ShowHidePlayerMessage::TYPE(dtEntity::SID("ShowHidePlayerMessage"));
|
||||
const dtEntity::StringId ShowHidePlayerMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
|
||||
ShowHidePlayerMessage::ShowHidePlayerMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType DisplayNameClickedMessage::TYPE(dtEntity::SID("DisplayNameClickedMessage"));
|
||||
const dtEntity::StringId DisplayNameClickedMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId DisplayNameClickedMessage::PositionId(dtEntity::SID("Position"));
|
||||
|
||||
|
||||
DisplayNameClickedMessage::DisplayNameClickedMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(AboutEntityId, &mAboutEntity);
|
||||
this->Register(PositionId, &mPosition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/messagefactory.h>
|
||||
#include <dtEntity/message.h>
|
||||
#include <dtEntity/property.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
void RegisterMessageTypes(dtEntity::MessageFactory& em);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class NavMeshGroupChangedMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
// type identifier of this message class
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId GroupNameId;
|
||||
static const dtEntity::StringId PreviousGroupNameId;
|
||||
|
||||
NavMeshGroupChangedMessage();
|
||||
|
||||
// Create a copy of this message on the heap
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<NavMeshGroupChangedMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId id) { mAboutEntity.Set(id); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetGroupName(const std::string& v) { mGroupName.Set(v); }
|
||||
std::string GetGroupName() const { return mGroupName.Get(); }
|
||||
|
||||
void SetPreviousGroupName(const std::string& v) { mPreviousGroupName.Set(v); }
|
||||
std::string GetPreviousGroupName() const { return mPreviousGroupName.Get(); }
|
||||
private:
|
||||
|
||||
dtEntity::IntProperty mAboutEntity;
|
||||
dtEntity::StringProperty mGroupName;
|
||||
dtEntity::StringProperty mPreviousGroupName;
|
||||
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class TransformSendMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId PositionId;
|
||||
static const dtEntity::StringId AttitudeId;
|
||||
static const dtEntity::StringId RoomNumberId;
|
||||
|
||||
TransformSendMessage();
|
||||
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<TransformSendMessage>(); }
|
||||
|
||||
void SetAboutEntity(dtEntity::EntityId id) { mAboutEntity.Set(id); }
|
||||
dtEntity::EntityId GetAboutEntity() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetPosition(const osg::Vec3f& id) { mPosition.Set(id); }
|
||||
osg::Vec3f GetPosition() const { return mPosition.Get(); }
|
||||
|
||||
void SetAttitude(const osg::Quat& id) { mAttitude.Set(id); }
|
||||
osg::Quat GetAttitude() const { return mAttitude.Get(); }
|
||||
|
||||
void SetRoomNumber(dtEntity::EntityId roomNumber) { mRoomNumber.Set(roomNumber); }
|
||||
dtEntity::EntityId GetRoomNumber() const { return mRoomNumber.Get(); }
|
||||
|
||||
private:
|
||||
|
||||
dtEntity::UIntProperty mAboutEntity;
|
||||
dtEntity::Vec3Property mPosition;
|
||||
dtEntity::QuatProperty mAttitude;
|
||||
dtEntity::UIntProperty mRoomNumber;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class PlayerPickedMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId PositionId;
|
||||
|
||||
PlayerPickedMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<PlayerPickedMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId v) { mAboutEntity.Set(v); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetPosition(const osg::Vec3f& v) { mPosition.Set(v); }
|
||||
osg::Vec3f GetPosition() const { return mPosition.Get(); }
|
||||
|
||||
private:
|
||||
dtEntity::UIntProperty mAboutEntity;
|
||||
dtEntity::Vec3Property mPosition;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FastForwardMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
// type identifier of this message class
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId EndTimeId;
|
||||
|
||||
FastForwardMessage();
|
||||
|
||||
// Create a copy of this message on the heap
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<FastForwardMessage>(); }
|
||||
|
||||
void SetEndTime(double v) { mEndTime.Set(v); }
|
||||
double GetEndTime() const { return mEndTime.Get(); }
|
||||
|
||||
private:
|
||||
|
||||
dtEntity::DoubleProperty mEndTime;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class HideSelectionMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId NameFlagId;
|
||||
|
||||
HideSelectionMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<HideSelectionMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId v) { mAboutEntity.Set(v); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetNameFlagId(bool v) { mNameFlag.Set(v); }
|
||||
bool GetNameFlagId() const { return mNameFlag.Get(); }
|
||||
|
||||
private:
|
||||
dtEntity::UIntProperty mAboutEntity;
|
||||
dtEntity::BoolProperty mNameFlag;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class RemoveShootMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
|
||||
RemoveShootMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<RemoveShootMessage>(); }
|
||||
|
||||
void SetId(int32_t id) { mId = id; }
|
||||
int32_t GetId() { return mId; }
|
||||
|
||||
private:
|
||||
int32_t mId { 0 };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class ShootMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
|
||||
ShootMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<ShootMessage>(); }
|
||||
|
||||
void SetShooter(dtEntity::EntityId v) { mShooter = v; }
|
||||
dtEntity::EntityId GetShooter() const { return mShooter; }
|
||||
void SetShooterPos(const dtEntity::Vec3d &shooterPos) { mShooterPos = shooterPos; }
|
||||
dtEntity::Vec3d GetShooterPos() const { return mShooterPos; }
|
||||
|
||||
void SetTarget(dtEntity::EntityId v) { mTarget = v; }
|
||||
dtEntity::EntityId GetTarget() const { return mTarget; }
|
||||
void SetTargetPos(const dtEntity::Vec3d &targetPos) { mTargetPos = targetPos; }
|
||||
dtEntity::Vec3d GetTargetPos() const { return mTargetPos; }
|
||||
|
||||
void SetBuildingIdSrc(dtEntity::EntityId v) { mBuildingIdSrc = v; }
|
||||
dtEntity::EntityId GetBuildingIdSrc() const { return mBuildingIdSrc; }
|
||||
void SetRoomNumberSrc(const dtEntity::EntityId &v) { mRoomNumberSrc = v; }
|
||||
dtEntity::EntityId GetRoomNumberSrc() const { return mRoomNumberSrc; }
|
||||
|
||||
void SetBuildingIdDst(dtEntity::EntityId v) { mBuildingIdDst = v; }
|
||||
dtEntity::EntityId GetBuildingIdDst() const { return mBuildingIdDst; }
|
||||
void SetRoomNumberDst(const dtEntity::EntityId &v) { mRoomNumberDst = v; }
|
||||
dtEntity::EntityId GetRoomNumberDst() const { return mRoomNumberDst; }
|
||||
|
||||
void SetDuration(float v) { mDuration = v; }
|
||||
float GetDuration() const { return mDuration; }
|
||||
|
||||
void SetLineType(int v) { mLineType = v; }
|
||||
float GetLineType() const { return mLineType; }
|
||||
|
||||
void SetSimTimeCreated(double v) { mSimTimeCreated = v; }
|
||||
double GetSimTimeCreated() const { return mSimTimeCreated; }
|
||||
|
||||
void SetId(int32_t id) { mId = id; }
|
||||
int32_t GetId() const { return mId; }
|
||||
|
||||
private:
|
||||
int32_t mId { 0 };
|
||||
dtEntity::Vec3d mShooterPos;
|
||||
dtEntity::Vec3d mTargetPos;
|
||||
dtEntity::EntityId mShooter = 0;
|
||||
dtEntity::EntityId mTarget = 0;
|
||||
dtEntity::EntityId mBuildingIdSrc = 0;
|
||||
dtEntity::EntityId mRoomNumberSrc = 0;
|
||||
dtEntity::EntityId mBuildingIdDst = 0;
|
||||
dtEntity::EntityId mRoomNumberDst = 0;
|
||||
int mLineType = 0;
|
||||
float mDuration = 0.f;
|
||||
double mSimTimeCreated = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class ShowHidePlayerMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
|
||||
ShowHidePlayerMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<ShowHidePlayerMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId v) { mAboutEntity.Set(v); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetShow(bool v) { mShow = v; }
|
||||
bool GetShow() const { return mShow; }
|
||||
|
||||
private:
|
||||
dtEntity::UIntProperty mAboutEntity = 0;
|
||||
bool mShow = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class DisplayNameClickedMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId PositionId;
|
||||
|
||||
DisplayNameClickedMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<DisplayNameClickedMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId v) { mAboutEntity.Set(v); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetPosition(const osg::Vec3f& v) { mPosition.Set(v); }
|
||||
osg::Vec3f GetPosition() const { return mPosition.Get(); }
|
||||
|
||||
private:
|
||||
dtEntity::UIntProperty mAboutEntity;
|
||||
dtEntity::Vec3Property mPosition;
|
||||
};
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
#include "modelsplittercomponent.h"
|
||||
|
||||
#include "visitors.h"
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/layerattachpointcomponent.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QSet>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId ModelSplitterComponent::TYPE(dtEntity::SID("ModelSplitter"));
|
||||
const dtEntity::StringId ModelSplitterComponent::VerticalDisplaceId(dtEntity::SID("VerticalDisplace"));
|
||||
const dtEntity::StringId ModelSplitterComponent::HorizontalDisplaceId(dtEntity::SID("HorizontalDisplace"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
ModelSplitterComponent::ModelSplitterComponent()
|
||||
{
|
||||
Register(VerticalDisplaceId, &mVerticalDisplace);
|
||||
Register(HorizontalDisplaceId, &mHorizontalDisplace);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void ModelSplitterComponent::OnAddedToEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
BaseClass::OnAddedToEntity(entity);
|
||||
mEntity = &entity;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void ModelSplitterComponent::Split(std::vector<dtEntity::EntityId> &eids, std::vector<float> &heights, std::vector<int> &floors, dtEntity::StringId layerName)
|
||||
{
|
||||
|
||||
dtEntityOSG::StaticMeshComponent *smc;
|
||||
if (!mEntity->GetComponent(smc))
|
||||
{
|
||||
LOG_ERROR("Cannot split: Has no staticmeshcomponent");
|
||||
return;
|
||||
}
|
||||
osg::ref_ptr<osg::Node> mesh = osgDB::readNodeFile(smc->GetMesh());
|
||||
if (mesh == nullptr) return;
|
||||
|
||||
SplitVisitor v;
|
||||
mesh->accept(v);
|
||||
heights = v._heights;
|
||||
mesh = nullptr;
|
||||
|
||||
for (const auto &part : v._parts)
|
||||
{
|
||||
osg::ref_ptr<osg::Node> node = osg::clone(part.get(), osg::CopyOp(
|
||||
osg::CopyOp::DEEP_COPY_OBJECTS |
|
||||
osg::CopyOp::DEEP_COPY_NODES |
|
||||
osg::CopyOp::DEEP_COPY_USERDATA
|
||||
));
|
||||
|
||||
|
||||
dtEntity::Entity *e;
|
||||
if (!mEntity->GetEntityManager().CreateEntity(e))
|
||||
continue;
|
||||
eids.push_back(e->GetId());
|
||||
|
||||
std::string nname = node->getName();
|
||||
std::string floorstr = nname.substr(6, nname.size() - 1);
|
||||
|
||||
int floor = QString::fromStdString(floorstr).toInt();
|
||||
floors.push_back(floor);
|
||||
|
||||
std::ostringstream entityname;
|
||||
entityname << dtEntity::GetStringFromSID(layerName) << "_" << floorstr;
|
||||
|
||||
dtEntity::MapComponent *mc;
|
||||
if (!e->CreateComponent(mc))
|
||||
continue;
|
||||
mc->SetEntityName(entityname.str());
|
||||
mc->SetUniqueId(entityname.str());
|
||||
mc->SetMapName("parts");
|
||||
|
||||
dtEntityOSG::StaticMeshComponent *smcFloor;
|
||||
if (!e->CreateComponent(smcFloor))
|
||||
continue;
|
||||
smcFloor->SetStaticMesh(node);
|
||||
dtEntityOSG::PositionAttitudeTransformComponent *pc;
|
||||
if (!e->CreateComponent(pc))
|
||||
continue;
|
||||
pc->AddChildComponent(smcFloor->GetType());
|
||||
|
||||
dtEntityOSG::LayerComponent *lc;
|
||||
if (!e->CreateComponent(lc))
|
||||
continue;
|
||||
lc->SetAttachedComponent(pc->GetType());
|
||||
lc->SetLayer(layerName);
|
||||
lc->Finished();
|
||||
|
||||
}
|
||||
|
||||
// sort
|
||||
std::sort(floors.begin(), floors.end());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId ModelSplitterSystem::TYPE(dtEntity::SID("ModelSplitter"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
ModelSplitterSystem::ModelSplitterSystem(dtEntity::EntityManager &em)
|
||||
: dtEntity::DefaultEntitySystem<ModelSplitterComponent>(em)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/message.h>
|
||||
#include <dtEntity/stringid.h>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
#include <dtEntity/scriptaccessor.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
class ModelSplitterComponent final : public dtEntity::Component
|
||||
{
|
||||
|
||||
using BaseClass = dtEntity::Component;
|
||||
|
||||
public:
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
static const dtEntity::StringId VerticalDisplaceId;
|
||||
static const dtEntity::StringId HorizontalDisplaceId;
|
||||
|
||||
|
||||
ModelSplitterComponent();
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override;
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
void Split(std::vector<dtEntity::EntityId> &eids, std::vector<float> &heights, std::vector<int> &floors, dtEntity::StringId layerName);
|
||||
|
||||
dtEntity::FloatProperty mVerticalDisplace;
|
||||
dtEntity::Vec2Property mHorizontalDisplace;
|
||||
|
||||
void SetBuildingId(dtEntity::StringId id) { mBuildingId = id; }
|
||||
dtEntity::StringId GetBuildingId() const { return mBuildingId; }
|
||||
|
||||
private:
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
dtEntity::StringId mBuildingId = 0;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
class ModelSplitterSystem final
|
||||
: public dtEntity::DefaultEntitySystem<ModelSplitterComponent>
|
||||
, public dtEntity::ScriptAccessor
|
||||
{
|
||||
public:
|
||||
explicit ModelSplitterSystem(dtEntity::EntityManager &em);
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
#include "motionmodel.h"
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/systeminterface.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
#include <osg/io_utils>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId MotionModelComponent::TYPE(dtEntity::SID("MotionModel"));
|
||||
|
||||
const dtEntity::StringId MotionModelComponent::ContextIdId(dtEntity::SID("ContextId"));
|
||||
const dtEntity::StringId MotionModelComponent::MoveSpeedId(dtEntity::SID("MoveSpeed"));
|
||||
const dtEntity::StringId MotionModelComponent::RotateSpeedId(dtEntity::SID("RotateSpeed"));
|
||||
const dtEntity::StringId MotionModelComponent::RotateKeySpeedId(dtEntity::SID("RotateKeySpeed"));
|
||||
const dtEntity::StringId MotionModelComponent::EnabledId(dtEntity::SID("Enabled"));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId MotionModelSystem::TYPE(dtEntity::SID("MotionModel"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
MotionModelComponent::MotionModelComponent()
|
||||
{
|
||||
Register(ContextIdId, &mContextId);
|
||||
Register(MoveSpeedId, &mMoveSpeed);
|
||||
Register(RotateSpeedId, &mRotateSpeed);
|
||||
Register(RotateKeySpeedId, &mRotateKeySpeed);
|
||||
Register(EnabledId, &mEnabled);
|
||||
|
||||
mContextId.Set(0);
|
||||
mMoveSpeed.Set(100);
|
||||
mRotateSpeed.Set(0.001f);
|
||||
mRotateKeySpeed.Set(2);
|
||||
mEnabled.Set(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelComponent::OnAddedToEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
mEntity = &entity;
|
||||
dtEntity::GetInputInterface()->AddInputCallback(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelComponent::OnRemovedFromEntity(dtEntity::Entity &)
|
||||
{
|
||||
mEntity = nullptr;
|
||||
dtEntity::GetInputInterface()->RemoveInputCallback(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelComponent::Finished()
|
||||
{
|
||||
assert(mEntity != nullptr);
|
||||
bool success = mEntity->GetComponent(mCamera);
|
||||
if (success)
|
||||
mContextId.Set(mCamera->GetContextId());
|
||||
else
|
||||
LOG_ERROR("MotionModelComponent on entity without camera component!");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::KeyUp(const std::string &key, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (!handled && mEnabled.Get() && (int)contextid == mContextId.Get())
|
||||
{
|
||||
if (key == "t")
|
||||
{
|
||||
osg::Vec3d campos = mCamera->GetPosition();
|
||||
LOG_ALWAYS("Translation: " << campos)
|
||||
}
|
||||
else if (key == "1") mMoveSpeed.Set(5);
|
||||
else if (key == "2") mMoveSpeed.Set(15);
|
||||
else if (key == "3") mMoveSpeed.Set(40);
|
||||
else if (key == "4") mMoveSpeed.Set(100);
|
||||
else if (key == "5") mMoveSpeed.Set(250);
|
||||
else if (key == "6") mMoveSpeed.Set(600);
|
||||
else if (key == "7") mMoveSpeed.Set(1500);
|
||||
else if (key == "8") mMoveSpeed.Set(4000);
|
||||
else if (key == "9") mMoveSpeed.Set(9000);
|
||||
else if (key == "0") mMoveSpeed.Set(20000);
|
||||
else if (key == "KP_Add") mMoveSpeed.Set(mMoveSpeed.Get() * 1.1f);
|
||||
else if (key == "KP_Subtract") mMoveSpeed.Set(mMoveSpeed.Get() / 1.1f);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::KeyDown(const std::string &, bool, unsigned int)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::MouseButtonUp(int button, bool, unsigned int contextid)
|
||||
{
|
||||
if (!mEnabled.Get() || (int)contextid != mContextId.Get()) return false;
|
||||
if (button == 1 || button == 2)
|
||||
dtEntity::GetInputInterface()->SetLockCursor(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::MouseButtonDown(int button, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (handled) return false;
|
||||
if (!mEnabled.Get() || (int)contextid != mContextId.Get()) return false;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
if (button == 1)
|
||||
inputif->SetLockCursor(true);
|
||||
else if (button == 2)
|
||||
{
|
||||
// do intersection test to get pivot point to rotate around
|
||||
inputif->SetLockCursor(true);
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseXId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseYId);
|
||||
osg::Vec3 pickray = dtEntity::GetWindowInterface()->GetPickRay(contextid, mouseX, mouseY);
|
||||
osg::Vec3d campos = mCamera->GetPosition();
|
||||
|
||||
std::vector<dtEntity::WindowInterface::Intersection> isects;
|
||||
bool found = dtEntity::GetWindowInterface()->GetIntersections(campos, campos + pickray * 10000, isects);
|
||||
if (found)
|
||||
mPivot = isects.front().mPosition;
|
||||
else
|
||||
mPivot = campos + pickray * 100;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::MouseWheel(int dir, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (!mEnabled.Get())
|
||||
return false;
|
||||
|
||||
if (!handled && mCamera != nullptr && mContextId.Get() == (int)contextid)
|
||||
{
|
||||
osg::Vec3d campos = mCamera->GetPosition();
|
||||
osg::Vec3d eyedir = mCamera->GetEyeDirection();
|
||||
mCamera->SetPosition(campos + eyedir * dir * 20);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::MouseMove(float, float, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (handled)
|
||||
return false;
|
||||
|
||||
if (mCamera == nullptr || !mEnabled.Get() || mContextId.Get() != (int)contextid)
|
||||
return false;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseDeltaXRawId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseDeltaYRawId);
|
||||
|
||||
osg::Vec3d up = mCamera->GetUp();
|
||||
osg::Vec3d eyedir = mCamera->GetEyeDirection();
|
||||
osg::Vec3d toRight = eyedir ^ up;
|
||||
|
||||
if (inputif->GetMouseButton(1, mContextId.Get()))
|
||||
{
|
||||
osg::Quat rotateop1; rotateop1.makeRotate(-mouseX * mRotateSpeed.Get(), up);
|
||||
osg::Quat rotateop2; rotateop2.makeRotate(mouseY * mRotateSpeed.Get(), toRight);
|
||||
eyedir = (rotateop1 * rotateop2) * eyedir;
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
else if (inputif->GetMouseButton(2, mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d pivotToCam = mCamera->GetPosition() - mPivot;
|
||||
osg::Quat rotateop1; rotateop1.makeRotate(mouseX * -0.001f, up);
|
||||
osg::Quat rotateop2; rotateop2.makeRotate(mouseY * 0.001f, toRight);
|
||||
pivotToCam = (rotateop1 * rotateop2) * pivotToCam;
|
||||
mCamera->SetPosition(pivotToCam + mPivot);
|
||||
|
||||
pivotToCam *= -1;
|
||||
pivotToCam.normalize();
|
||||
mCamera->SetEyeDirection(pivotToCam);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelComponent::Tick(float dt)
|
||||
{
|
||||
if (mCamera == nullptr || !mEnabled.Get())
|
||||
return;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
|
||||
float speed = mMoveSpeed.Get();
|
||||
if (inputif->GetKey("Shift_L", mContextId.Get()))
|
||||
speed *= 4;
|
||||
|
||||
bool modified = false;
|
||||
if (inputif->GetKey("w", mContextId.Get()))
|
||||
{
|
||||
mCamera->SetPosition(mCamera->GetPosition() + mCamera->GetEyeDirection() * (dt * speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("s", mContextId.Get()))
|
||||
{
|
||||
mCamera->SetPosition(mCamera->GetPosition() + mCamera->GetEyeDirection() * (dt * -speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("a", mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d toRight = mCamera->GetEyeDirection() ^ mCamera->GetUp();
|
||||
mCamera->SetPosition(mCamera->GetPosition() + toRight * (dt * -speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("d", mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d toRight = mCamera->GetEyeDirection() ^ mCamera->GetUp();
|
||||
mCamera->SetPosition(mCamera->GetPosition() + toRight * (dt * speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("q", mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d toRight = mCamera->GetEyeDirection() ^ mCamera->GetUp();
|
||||
mCamera->SetPosition(mCamera->GetPosition() + (toRight ^ mCamera->GetEyeDirection()) * (dt * -speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("e", mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d toRight = mCamera->GetEyeDirection() ^ mCamera->GetUp();
|
||||
mCamera->SetPosition(mCamera->GetPosition() + (toRight ^ mCamera->GetEyeDirection()) * (dt * speed));
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (inputif->GetKey("Left", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(dt * mRotateKeySpeed.Get(), mCamera->GetUp());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Right", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(-dt * mRotateKeySpeed.Get(), mCamera->GetUp());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Up", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(-dt * mRotateKeySpeed.Get(), mCamera->GetUp() ^ mCamera->GetEyeDirection());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Down", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(dt * mRotateKeySpeed.Get(), mCamera->GetUp() ^ mCamera->GetEyeDirection());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
mCamera->UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
MotionModelSystem::MotionModelSystem(dtEntity::EntityManager &em)
|
||||
: BaseClass(em)
|
||||
{
|
||||
mTickFunctor = dtEntity::MessageFunctor(this, &MotionModelSystem::Tick);
|
||||
GetEntityManager().RegisterForMessages(dtEntity::TickMessage::TYPE,
|
||||
mTickFunctor, dtEntity::FilterOptions::ORDER_DEFAULT, "MotionModelSystem::Tick");
|
||||
|
||||
mMoveToPosFunctor = dtEntity::MessageFunctor(this, &MotionModelSystem::MoveToPos);
|
||||
GetEntityManager().RegisterForMessages(dtEntity::MoveCameraToPositionMessage::TYPE,
|
||||
mMoveToPosFunctor, dtEntity::FilterOptions::ORDER_DEFAULT, "MotionModelSystem::MoveToPos");
|
||||
|
||||
mMoveToEntityFunctor = dtEntity::MessageFunctor(this, &MotionModelSystem::MoveToEntity);
|
||||
GetEntityManager().RegisterForMessages(dtEntity::MoveCameraToEntityMessage::TYPE,
|
||||
mMoveToEntityFunctor, dtEntity::FilterOptions::ORDER_DEFAULT, "MotionModelSystem::MoveToEntity");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelSystem::Tick(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::TickMessage &msg = static_cast<const dtEntity::TickMessage &>(m);
|
||||
for (auto i : mComponents)
|
||||
i.second->Tick(msg.GetDeltaRealTime());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelSystem::MoveToPos(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::MoveCameraToPositionMessage &msg = static_cast<const dtEntity::MoveCameraToPositionMessage &>(m);
|
||||
for (auto i : mComponents)
|
||||
{
|
||||
MotionModelComponent *mmc = i.second;
|
||||
if ((int)mmc->GetContextId() == msg.GetContextId())
|
||||
{
|
||||
dtEntityOSG::CameraComponent *cam = mmc->GetCamera();
|
||||
if (cam)
|
||||
{
|
||||
cam->SetPosition(msg.GetPosition());
|
||||
osg::Vec3d eyedir = msg.GetLookAt() - msg.GetPosition();
|
||||
eyedir.normalize();
|
||||
cam->SetEyeDirection(eyedir);
|
||||
cam->SetUp(msg.GetUp());
|
||||
cam->UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelSystem::MoveToEntity(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::MoveCameraToEntityMessage &msg = static_cast<const dtEntity::MoveCameraToEntityMessage &>(m);
|
||||
|
||||
dtEntityOSG::TransformComponent *transcomp;
|
||||
if (!GetEntityManager().GetComponent(msg.GetAboutEntityId(), transcomp, true))
|
||||
{
|
||||
LOG_ERROR("Cannot jump to entity: has no transform component!");
|
||||
return;
|
||||
}
|
||||
osg::Vec3d targetpos = transcomp->GetTranslation();
|
||||
|
||||
for (auto i : mComponents)
|
||||
{
|
||||
MotionModelComponent *mmc = i.second;
|
||||
if ((int)mmc->GetContextId() != msg.GetContextId()) continue;
|
||||
|
||||
dtEntityOSG::CameraComponent *cam = mmc->GetCamera();
|
||||
if (!cam) continue;
|
||||
|
||||
if (msg.GetKeepCameraDirection())
|
||||
{
|
||||
osg::Vec3d eyedir = cam->GetEyeDirection();
|
||||
eyedir *= msg.GetDistance();
|
||||
cam->SetPosition(targetpos - eyedir);
|
||||
cam->UpdateViewMatrix();
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Vec3d eyedir = targetpos - cam->GetPosition();
|
||||
eyedir.normalize();
|
||||
cam->SetEyeDirection(eyedir);
|
||||
cam->SetPosition(targetpos + eyedir * -msg.GetDistance());
|
||||
cam->UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include <dtEntity/inputinterface.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class MotionModelComponent final
|
||||
: public dtEntity::Component
|
||||
, public dtEntity::InputCallbackInterface
|
||||
{
|
||||
public:
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
static const dtEntity::StringId ContextIdId;
|
||||
static const dtEntity::StringId MoveSpeedId;
|
||||
static const dtEntity::StringId RotateSpeedId;
|
||||
static const dtEntity::StringId RotateKeySpeedId;
|
||||
static const dtEntity::StringId EnabledId;
|
||||
|
||||
|
||||
MotionModelComponent();
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return (id == TYPE);
|
||||
}
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override;
|
||||
void OnRemovedFromEntity(dtEntity::Entity &) override;
|
||||
|
||||
void Finished() override;
|
||||
void Tick(float dt);
|
||||
|
||||
unsigned int GetContextId() const { return mContextId.Get(); }
|
||||
void SetContextId(unsigned int i) { mContextId.Set(i); }
|
||||
|
||||
bool KeyUp(const std::string &key, bool handled, unsigned int contextid) override;
|
||||
bool KeyDown(const std::string &name, bool handled, unsigned int contextid) override;
|
||||
bool MouseButtonUp(int button, bool handled, unsigned int contextid) override;
|
||||
bool MouseButtonDown(int button, bool handled, unsigned int contextid) override;
|
||||
bool MouseWheel(int dir, bool handled, unsigned int contextid) override;
|
||||
bool MouseMove(float x, float y, bool handled, unsigned int contextid) override;
|
||||
void MouseEnterLeave(bool, unsigned int) override {}
|
||||
|
||||
dtEntityOSG::CameraComponent *GetCamera() const { return mCamera; }
|
||||
private:
|
||||
dtEntity::IntProperty mContextId;
|
||||
dtEntity::UIntProperty mMoveSpeed;
|
||||
dtEntity::FloatProperty mRotateSpeed;
|
||||
dtEntity::FloatProperty mRotateKeySpeed;
|
||||
dtEntity::BoolProperty mEnabled;
|
||||
dtEntityOSG::CameraComponent *mCamera = nullptr;
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
osg::Vec3d mPivot;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class MotionModelSystem final
|
||||
: public dtEntity::DefaultEntitySystem<MotionModelComponent>
|
||||
{
|
||||
using BaseClass = dtEntity::DefaultEntitySystem<MotionModelComponent>;
|
||||
|
||||
public:
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
|
||||
explicit MotionModelSystem(dtEntity::EntityManager &em);
|
||||
|
||||
private:
|
||||
|
||||
void Tick(const dtEntity::Message &m);
|
||||
void MoveToPos(const dtEntity::Message &m);
|
||||
void MoveToEntity(const dtEntity::Message &m);
|
||||
|
||||
dtEntity::MessageFunctor mTickFunctor;
|
||||
dtEntity::MessageFunctor mMoveToPosFunctor;
|
||||
dtEntity::MessageFunctor mMoveToEntityFunctor;
|
||||
};
|
||||
}
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
#include "orthomotionmodel.h"
|
||||
|
||||
#include "messages.h"
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/profile.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/systeminterface.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/layerattachpointcomponent.h>
|
||||
#include <dtEntityOSG/skyboxcomponent.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
#include <osgViewer/View>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
constexpr int LeftMouseButton = 0;
|
||||
//const int RightMouseButton = 1;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId OrthoMotionModelComponent::TYPE(dtEntity::SID("OrthoMotionModel"));
|
||||
|
||||
const dtEntity::StringId OrthoMotionModelComponent::ContextIdId(dtEntity::SID("ContextId"));
|
||||
const dtEntity::StringId OrthoMotionModelComponent::EnabledId(dtEntity::SID("Enabled"));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId OrthoMotionModelSystem::TYPE(dtEntity::SID("OrthoMotionModel"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
OrthoMotionModelComponent::OrthoMotionModelComponent()
|
||||
{
|
||||
Register(ContextIdId, &mContextId);
|
||||
Register(EnabledId, &mEnabled);
|
||||
|
||||
mContextId.Set(0);
|
||||
mEnabled.Set(true);
|
||||
|
||||
m_mouseMovedWhileLeftButtonPressed = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::OnAddedToEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
mEntity = &entity;
|
||||
dtEntity::GetInputInterface()->AddInputCallback(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::OnRemovedFromEntity(dtEntity::Entity &)
|
||||
{
|
||||
mEntity = nullptr;
|
||||
dtEntity::GetInputInterface()->RemoveInputCallback(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::Finished()
|
||||
{
|
||||
assert(mEntity != nullptr);
|
||||
bool success = mEntity->GetComponent(mCamera);
|
||||
if (success)
|
||||
mContextId.Set(mCamera->GetContextId());
|
||||
else
|
||||
LOG_ERROR("MotionModelComponent on entity without camera component!");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool OrthoMotionModelComponent::MouseButtonUp(int button, bool handled, unsigned int contextid)
|
||||
{
|
||||
(void)(handled);
|
||||
if (!mEnabled.Get() || (int)contextid != mContextId.Get()) return false;
|
||||
|
||||
if (button == LeftMouseButton)
|
||||
{
|
||||
if(!m_mouseMovedWhileLeftButtonPressed)
|
||||
{
|
||||
/*
|
||||
* Mouse has not been moved, this means user clicked and immediately released the left button.
|
||||
* This means: Select object under cursor (if existent)
|
||||
*/
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseXRawId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseYRawId);
|
||||
dtEntityOSG::CameraSystem *camsys;
|
||||
mEntity->GetEntityManager().GetES(camsys);
|
||||
if (!camsys)
|
||||
return false;
|
||||
dtEntity::EntityId camid = camsys->GetCameraEntityByContextId(mContextId.Get());
|
||||
dtEntityOSG::CameraComponent *camcomp;
|
||||
mEntity->GetEntityManager().GetComponent(camid, camcomp);
|
||||
if (!camcomp)
|
||||
return false;
|
||||
|
||||
osgUtil::LineSegmentIntersector::Intersections isects;
|
||||
osgViewer::View *v = dynamic_cast<osgViewer::View *>(camcomp->GetCamera()->getView());
|
||||
bool found = v->computeIntersections(mouseX, mouseY, isects, 0xFFFFFFFF);
|
||||
|
||||
if (found)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersections::const_iterator i;
|
||||
for (const osgUtil::LineSegmentIntersector::Intersection &isect : isects)
|
||||
{
|
||||
for (osg::NodePath::const_reverse_iterator j = isect.nodePath.rbegin(); j != isect.nodePath.rend(); ++j)
|
||||
{
|
||||
const osg::Node *node = *j;
|
||||
if (node->getName() == "icon")
|
||||
{
|
||||
const osg::Referenced *referenced = node->getUserData();
|
||||
if (referenced == nullptr) continue;
|
||||
const dtEntityOSG::EntityData *ed = dynamic_cast<const dtEntityOSG::EntityData *>(referenced);
|
||||
if (ed != nullptr && ed->mEntity->GetId() != camid)
|
||||
{
|
||||
PlayerPickedMessage msg;
|
||||
msg.SetAboutEntityId(ed->mEntity->GetId());
|
||||
mEntity->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
}
|
||||
if(node->getName() == "text")
|
||||
{
|
||||
const osg::Referenced* referenced = node->getUserData();
|
||||
if(referenced == nullptr) continue;
|
||||
const dtEntityOSG::EntityData* ed = dynamic_cast<const dtEntityOSG::EntityData*>(referenced);
|
||||
if(ed != nullptr && ed->mEntity->GetId() != camid)
|
||||
{
|
||||
DisplayNameClickedMessage msg;
|
||||
msg.SetAboutEntityId(ed->mEntity->GetId());
|
||||
mEntity->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_mouseMovedWhileLeftButtonPressed = false;
|
||||
|
||||
dtEntity::GetInputInterface()->SetLockCursor(false);
|
||||
dtEntity::GetWindowInterface()->SetShowCursor(contextid, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool OrthoMotionModelComponent::MouseButtonDown(int button, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (handled) return false;
|
||||
if (!mEnabled.Get() || (int)contextid != mContextId.Get()) return false;
|
||||
|
||||
if (button == LeftMouseButton)
|
||||
{
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
inputif->SetLockCursor(true);
|
||||
dtEntity::GetWindowInterface()->SetShowCursor(contextid, false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool OrthoMotionModelComponent::MouseMove(float x, float y, bool handled, unsigned int contextid)
|
||||
{
|
||||
(void)(x);
|
||||
(void)(y);
|
||||
if (handled)
|
||||
return false;
|
||||
|
||||
if (mCamera == nullptr || !mEnabled.Get() || mContextId.Get() != (int)contextid)
|
||||
return false;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseDeltaXId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseDeltaYId);
|
||||
|
||||
if (inputif->GetMouseButton(LeftMouseButton, mContextId.Get()))
|
||||
{
|
||||
m_mouseMovedWhileLeftButtonPressed = true;
|
||||
|
||||
double left, right, bottom, top, znear, zfar;
|
||||
mCamera->GetCamera()->getProjectionMatrixAsOrtho(left, right, bottom, top, znear, zfar);
|
||||
|
||||
// scale movement speed by zoom factor
|
||||
float speed = -0.35f * (right - left);
|
||||
|
||||
left = left + speed * mouseX;
|
||||
right = right + speed * mouseX;
|
||||
bottom = bottom + speed * mouseY;
|
||||
top = top + speed * mouseY;
|
||||
|
||||
mCamera->SetOrthoLeft(left);
|
||||
mCamera->SetOrthoRight(right);
|
||||
mCamera->SetOrthoBottom(bottom);
|
||||
mCamera->SetOrthoTop(top);
|
||||
|
||||
mCamera->UpdateViewMatrix();
|
||||
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
|
||||
|
||||
if(m_callbackCamPosChanged)
|
||||
{
|
||||
m_callbackCamPosChanged(GetContextId(), BuildingViewer::CameraViewPosition(left, right, bottom, top));
|
||||
}
|
||||
}
|
||||
/*else if(inputif->GetMouseButton(LeftButton, mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d up = mCamera->GetUp();
|
||||
osg::Vec3d eyedir = mCamera->GetEyeDirection();
|
||||
osg::Vec3d toRight = eyedir ^ up;
|
||||
osg::Vec3d pivotToCam = mCamera->GetPosition();
|
||||
osg::Quat rotateop1; rotateop1.makeRotate(mouseX * -0.001f, up);
|
||||
osg::Quat rotateop2; rotateop2.makeRotate(mouseY * 0.001f, toRight);
|
||||
pivotToCam = (rotateop1 * rotateop2) * pivotToCam;
|
||||
osg::Vec3d eyedir = pivotToCam;
|
||||
eyedir *= -1;
|
||||
eyedir.normalize();
|
||||
if(fabs(eyedir[2]) < 0.99f)
|
||||
{
|
||||
mCamera->SetPosition(pivotToCam);
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
}*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::performZoom(int dir, const osg::Vec2& zoompoint)
|
||||
{
|
||||
double left, right, bottom, top, znear, zfar;
|
||||
mCamera->GetCamera()->getProjectionMatrixAsOrtho(left, right, bottom, top, znear, zfar);
|
||||
|
||||
osg::Vec2 zoompointabs(right * zoompoint[0] + left * (1 - zoompoint[0]),
|
||||
top * zoompoint[1] + bottom * (1 - zoompoint[1]));
|
||||
|
||||
float zoom = 1.0f - dir * 0.2f;
|
||||
|
||||
left = zoompointabs[0] - (zoompointabs[0] - left) * zoom;
|
||||
right = zoompointabs[0] - (zoompointabs[0] - right) * zoom;
|
||||
bottom = zoompointabs[1] - (zoompointabs[1] - bottom) * zoom;
|
||||
top = zoompointabs[1] - (zoompointabs[1] - top) * zoom;
|
||||
|
||||
mCamera->SetOrthoLeft(left);
|
||||
mCamera->SetOrthoRight(right);
|
||||
mCamera->SetOrthoBottom(bottom);
|
||||
mCamera->SetOrthoTop(top);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
|
||||
if(m_callbackCamPosChanged)
|
||||
{
|
||||
m_callbackCamPosChanged(GetContextId(), BuildingViewer::CameraViewPosition(left, right, bottom, top));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool OrthoMotionModelComponent::MouseWheel(int dir, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (!mEnabled.Get())
|
||||
return false;
|
||||
|
||||
if (!handled && mCamera != nullptr && mContextId.Get() == (int)contextid)
|
||||
{
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseXId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseYId);
|
||||
|
||||
osg::Vec2 zoompoint(0.5f, 0.5f);
|
||||
int x, y, w, h;
|
||||
dtEntity::GetWindowInterface()->GetWindowGeometry(contextid, x, y, w, h);
|
||||
if (mouseX >= -1 && mouseX <= 1 && mouseY >= -1 && mouseY <= 1)
|
||||
{
|
||||
zoompoint[0] = (mouseX + 1) / 2.0f;
|
||||
zoompoint[1] = (mouseY + 1) / 2.0f;
|
||||
}
|
||||
|
||||
performZoom(dir, zoompoint);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::Tick(float dt)
|
||||
{
|
||||
static const dtEntity::StringId MotionModelTick = dtEntity::SID("MotionModel Tick");
|
||||
CProfileManager::Start_Profile(MotionModelTick);
|
||||
|
||||
if (mCamera == nullptr || !mEnabled.Get())
|
||||
return;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
|
||||
bool modified = false;
|
||||
osg::Vec3d pos = mCamera->GetPosition();
|
||||
|
||||
float rotateKeySpeed = 1.0f;
|
||||
if (inputif->GetKey("Left", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(dt * rotateKeySpeed, mCamera->GetUp());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Right", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(-dt * rotateKeySpeed, mCamera->GetUp());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Up", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(-dt * rotateKeySpeed, mCamera->GetUp() ^ mCamera->GetEyeDirection());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Down", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(dt * rotateKeySpeed, mCamera->GetUp() ^ mCamera->GetEyeDirection());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
mCamera->SetPosition(pos);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
OrthoMotionModelSystem::OrthoMotionModelSystem(dtEntity::EntityManager &em)
|
||||
: BaseClass(em)
|
||||
{
|
||||
/*mTickFunctor = dtEntity::MessageFunctor(this, &OrthoMotionModelSystem::Tick);
|
||||
GetEntityManager().RegisterForMessages(dtEntity::TickMessage::TYPE,
|
||||
mTickFunctor, dtEntity::FilterOptions::ORDER_DEFAULT, "OrthoMotionModelSystem::Tick");*/
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelSystem::OnRemoveFromEntityManager(dtEntity::EntityManager &)
|
||||
{
|
||||
for (const auto &comp : mComponents)
|
||||
dtEntity::GetInputInterface()->RemoveInputCallback(comp.second);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelSystem::Tick(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::TickMessage &msg = static_cast<const dtEntity::TickMessage &>(m);
|
||||
for (const auto &comp : mComponents)
|
||||
comp.second->Tick(msg.GetDeltaRealTime());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntity/inputinterface.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include "cameraviewposition.h"
|
||||
#include <functional>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class OrthoMotionModelComponent final
|
||||
: public dtEntity::Component
|
||||
, public dtEntity::InputCallbackInterface
|
||||
{
|
||||
public:
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
static const dtEntity::StringId ContextIdId;
|
||||
static const dtEntity::StringId EnabledId;
|
||||
|
||||
|
||||
OrthoMotionModelComponent();
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return (id == TYPE);
|
||||
}
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override;
|
||||
void OnRemovedFromEntity(dtEntity::Entity &entity) override;
|
||||
|
||||
void Finished() override;
|
||||
void Tick(float dt);
|
||||
|
||||
unsigned int GetContextId() const { return mContextId.Get(); }
|
||||
void SetContextId(unsigned int i) { mContextId.Set(i); }
|
||||
|
||||
bool MouseButtonUp(int button, bool handled, unsigned int contextid) override;
|
||||
bool MouseButtonDown(int button, bool handled, unsigned int contextid) override;
|
||||
bool MouseWheel(int dir, bool handled, unsigned int contextid) override;
|
||||
bool MouseMove(float x, float y, bool handled, unsigned int contextid) override;
|
||||
void MouseEnterLeave(bool, unsigned int) override {}
|
||||
|
||||
void performZoom(int dir, const osg::Vec2& zoompoint);
|
||||
|
||||
dtEntityOSG::CameraComponent *GetCamera() const { return mCamera; }
|
||||
|
||||
|
||||
// First parameter: contextID as returned by OrthoMotionModelComponent::GetContextId
|
||||
std::function<void(unsigned int, const BuildingViewer::CameraViewPosition &)> m_callbackCamPosChanged;
|
||||
|
||||
private:
|
||||
bool m_mouseMovedWhileLeftButtonPressed;
|
||||
|
||||
dtEntity::IntProperty mContextId;
|
||||
dtEntity::BoolProperty mEnabled;
|
||||
dtEntityOSG::CameraComponent *mCamera = nullptr;
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class OrthoMotionModelSystem final
|
||||
: public dtEntity::DefaultEntitySystem<OrthoMotionModelComponent>
|
||||
{
|
||||
using BaseClass = dtEntity::DefaultEntitySystem<OrthoMotionModelComponent>;
|
||||
|
||||
public:
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
|
||||
explicit OrthoMotionModelSystem(dtEntity::EntityManager &em);
|
||||
|
||||
void OnRemoveFromEntityManager(dtEntity::EntityManager &) override;
|
||||
|
||||
private:
|
||||
|
||||
void Tick(const dtEntity::Message &m);
|
||||
dtEntity::MessageFunctor mTickFunctor;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
#include "playercomponent.h"
|
||||
|
||||
#include "iconcomponent.h"
|
||||
#include "messages.h"
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/profile.h>
|
||||
#include <dtEntity/nodemasks.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <dtEntityOSG/shadercomponent.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct ShowHidePlayerCommand : public PlayerComponent::Command
|
||||
{
|
||||
bool mShow;
|
||||
|
||||
ShowHidePlayerCommand(double when, bool show)
|
||||
: Command(when)
|
||||
, mShow(show)
|
||||
{
|
||||
}
|
||||
|
||||
void Execute(PlayerComponent *component) override
|
||||
{
|
||||
dtEntityOSG::LayerComponent *lc;
|
||||
if (component->GetEntity()->GetComponent(lc))
|
||||
{
|
||||
lc->SetVisible(mShow);
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(0);
|
||||
}
|
||||
IconComponent *ic;
|
||||
if (component->GetEntity()->GetComponent(ic))
|
||||
ic->SetVisible(mShow);
|
||||
|
||||
ShowHidePlayerMessage msg;
|
||||
msg.SetAboutEntityId(component->GetEntity()->GetId());
|
||||
msg.SetShow(mShow);
|
||||
component->GetEntity()->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct TeleportToTargetCommand : public PlayerComponent::Command
|
||||
{
|
||||
osg::Vec3d mGoal;
|
||||
VCtrl::OBB mOBB;
|
||||
int mRoomNumber;
|
||||
std::string mRoomname;
|
||||
|
||||
TeleportToTargetCommand(double when, const osg::Vec3d& goal, const VCtrl::OBB& obb, int roomNumber, const std::string& roomname)
|
||||
: Command(when)
|
||||
, mGoal(goal)
|
||||
, mOBB(obb)
|
||||
, mRoomNumber(roomNumber)
|
||||
, mRoomname(roomname)
|
||||
{
|
||||
}
|
||||
|
||||
void Execute(PlayerComponent *component) override
|
||||
{
|
||||
dtEntityOSG::TransformComponent *tc = component->GetTransform();
|
||||
if (tc)
|
||||
{
|
||||
tc->SetTranslation(mGoal);
|
||||
tc->Finished();
|
||||
}
|
||||
else
|
||||
LOG_ERROR("Cannot teleport: no transform component!");
|
||||
component->PlaceAt(mGoal, mOBB, mRoomNumber, mRoomname);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct RemoveShootCommand : public PlayerComponent::Command
|
||||
{
|
||||
int mId;
|
||||
RemoveShootCommand(double when, int32_t id)
|
||||
: Command(when)
|
||||
, mId(id)
|
||||
{}
|
||||
|
||||
void Execute(PlayerComponent *component) override
|
||||
{
|
||||
dtEntity::EntityManager &em = component->GetEntity()->GetEntityManager();
|
||||
|
||||
RemoveShootMessage msg;
|
||||
msg.SetId(mId);
|
||||
em.EmitMessage(msg);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct ShootCommand : public PlayerComponent::Command
|
||||
{
|
||||
int mId;
|
||||
Vec3d mShooterPos;
|
||||
Vec3d mTargetPos;
|
||||
dtEntity::EntityId mShooter;
|
||||
dtEntity::EntityId mTarget;
|
||||
int mBuildingIdSrc;
|
||||
int mRoomNumberSrc;
|
||||
int mBuildingIdDst;
|
||||
int mRoomNumberDst;
|
||||
int mLineType;
|
||||
float mDuration;
|
||||
double mSimTimeCreated;
|
||||
|
||||
ShootCommand(double when, int id, dtEntity::EntityId shooter, dtEntity::EntityId target,
|
||||
const Vec3d &shooterPos, const Vec3d &targetPos,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst,
|
||||
int lineType, float duration)
|
||||
: Command(when)
|
||||
, mId(id)
|
||||
, mShooterPos(shooterPos)
|
||||
, mTargetPos(targetPos)
|
||||
, mShooter(shooter)
|
||||
, mTarget(target)
|
||||
, mBuildingIdSrc(buildingIdSrc)
|
||||
, mRoomNumberSrc(roomNumberSrc)
|
||||
, mBuildingIdDst(buildingIdDst)
|
||||
, mRoomNumberDst(roomNumberDst)
|
||||
, mLineType(lineType)
|
||||
, mDuration(duration)
|
||||
, mSimTimeCreated(when)
|
||||
{
|
||||
}
|
||||
|
||||
void Execute(PlayerComponent *component) override
|
||||
{
|
||||
dtEntity::EntityManager &em = component->GetEntity()->GetEntityManager();
|
||||
|
||||
// check if source/target is visible
|
||||
|
||||
dtEntity::Vec3d shooterpos(mShooterPos.x, mShooterPos.y, mShooterPos.z);
|
||||
dtEntity::Vec3d targetpos(mTargetPos.x, mTargetPos.y, mTargetPos.z);
|
||||
|
||||
// draw an arrow
|
||||
const osg::Vec4 shooterColor = component->GetColor();
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(shooterpos, targetpos, shooterColor, 2, mDuration, false);
|
||||
osg::Vec3d edge = shooterpos - targetpos;
|
||||
edge.normalize();
|
||||
edge *= 0.5f;
|
||||
osg::Quat q;
|
||||
q.makeRotate(osg::PI / 4.0, 0, 0, 1);
|
||||
|
||||
osg::Vec3d result = q * edge;
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(targetpos, targetpos + result, shooterColor, 2, mDuration, false);
|
||||
q.makeRotate(-osg::PI / 4.0, 0, 0, 1);
|
||||
result = q * edge;
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(targetpos, targetpos + result, shooterColor, 2, mDuration, false);
|
||||
|
||||
osg::Vec3d left = edge ^ osg::Vec3d(0, 0, 1);
|
||||
q.makeRotate(osg::PI / 4.0, left[0], left[1], left[2]);
|
||||
result = q * edge;
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(targetpos, targetpos + result, shooterColor, 2, mDuration, false);
|
||||
|
||||
q.makeRotate(-osg::PI / 4.0, left[0], left[1], left[2]);
|
||||
result = q * edge;
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(targetpos, targetpos + result, shooterColor, 2, mDuration, false);
|
||||
|
||||
ShootMessage msg;
|
||||
msg.SetId(mId);
|
||||
msg.SetShooter(mShooter);
|
||||
msg.SetShooterPos(osg::Vec3d(mShooterPos.x, mShooterPos.y, mShooterPos.z));
|
||||
msg.SetTarget(mTarget);
|
||||
msg.SetTargetPos(osg::Vec3d(mTargetPos.x, mTargetPos.y, mTargetPos.z));
|
||||
msg.SetBuildingIdSrc(mBuildingIdSrc);
|
||||
msg.SetRoomNumberSrc(mRoomNumberSrc);
|
||||
msg.SetBuildingIdDst(mBuildingIdDst);
|
||||
msg.SetRoomNumberDst(mRoomNumberDst);
|
||||
msg.SetLineType(mLineType);
|
||||
msg.SetDuration(mDuration);
|
||||
msg.SetSimTimeCreated(mSimTimeCreated);
|
||||
em.EmitMessage(msg);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId PlayerComponent::TYPE(dtEntity::SID("Player"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::OnAddedToEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
mEntity = &entity;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::OnRemovedFromEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
NavMeshGroupChangedMessage msg;
|
||||
msg.SetPreviousGroupName(dtEntity::GetStringFromSID(mCurrentCellGroup));
|
||||
msg.SetAboutEntityId(GetEntity()->GetId());
|
||||
msg.SetGroupName("");
|
||||
entity.GetEntityManager().EmitMessage(msg);
|
||||
|
||||
mEntity = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntityOSG::TransformComponent *PlayerComponent::GetTransform()
|
||||
{
|
||||
assert(mEntity != nullptr);
|
||||
if (mTransform == nullptr)
|
||||
{
|
||||
mEntity->GetComponent(mTransform, true);
|
||||
assert(mTransform);
|
||||
}
|
||||
return mTransform;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::ExecuteCommands(double timenow)
|
||||
{
|
||||
if (mCommands.empty())
|
||||
return;
|
||||
|
||||
double nexttime = timenow;
|
||||
osg::ref_ptr<Command> execcommand = nullptr;
|
||||
for (const auto &command : mCommands)
|
||||
{
|
||||
if (command->mStartTime < nexttime)
|
||||
{
|
||||
execcommand = command;
|
||||
nexttime = command->mStartTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (execcommand.valid())
|
||||
{
|
||||
mCommands.erase(execcommand);
|
||||
execcommand->Execute(this);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::PositionOnMesh(const VCtrl::OBB& bb, osg::Vec3d& pos, const std::string& roomname)
|
||||
{
|
||||
GetTransform()->SetTranslation(pos);
|
||||
mPreviousRoom = mCurrentRoom;
|
||||
mCurrentRoom = dtEntity::SID(roomname);
|
||||
|
||||
if (bb.mBuilding != mCurrentCellGroup)
|
||||
{
|
||||
NavMeshGroupChangedMessage msg;
|
||||
msg.SetPreviousGroupName(dtEntity::GetStringFromSID(mCurrentCellGroup));
|
||||
msg.SetAboutEntityId(GetEntity()->GetId());
|
||||
msg.SetGroupName(dtEntity::GetStringFromSID(bb.mBuilding));
|
||||
|
||||
mCurrentCellGroup = bb.mBuilding;
|
||||
|
||||
GetEntity()->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::PlaceAt(const osg::Vec3d &_goal, const VCtrl::OBB &obb, int roomNumber, const std::string &roomname)
|
||||
{
|
||||
LOG_DEBUG("PlayerComponent::PlaceAt: " << "mEntity='"<< mEntity << "'"
|
||||
<< ", _goal: x=" << _goal.x() << " y=" << _goal.y() << " z=" << _goal.z()
|
||||
<< ", roomNumber="<< roomNumber
|
||||
<< ", roomname='"<< roomname << "'");
|
||||
|
||||
osg::Vec3d pgoal = _goal;
|
||||
|
||||
PositionOnMesh(obb, pgoal, roomname);
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(0);
|
||||
|
||||
TransformSendMessage msg;
|
||||
msg.SetAboutEntity(mEntity->GetId());
|
||||
msg.SetPosition(pgoal);
|
||||
msg.SetRoomNumber(roomNumber);
|
||||
mEntity->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::SetColor(const osg::Vec4f &color)
|
||||
{
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::DeleteQueuedCommands()
|
||||
{
|
||||
mCommands.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
osg::Vec4f PlayerComponent::GetColor() const
|
||||
{
|
||||
return mColor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId PlayerSystem::TYPE(dtEntity::SID("Player"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
PlayerSystem::PlayerSystem(dtEntity::EntityManager &em)
|
||||
: dtEntity::DefaultEntitySystem<PlayerComponent>(em)
|
||||
{
|
||||
mTickFunctor = dtEntity::MessageFunctor(this, &PlayerSystem::OnTick);
|
||||
em.RegisterForMessages(dtEntity::TickMessage::TYPE, mTickFunctor, dtEntity::FilterOptions::ORDER_LATE, "PlayerSystem::OnTick");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::OnTick(const dtEntity::Message &m)
|
||||
{
|
||||
static const dtEntity::StringId PlayerSystemTick = dtEntity::SID("PlayerSystem Tick");
|
||||
CProfileManager::Start_Profile(PlayerSystemTick);
|
||||
|
||||
const dtEntity::TickMessage &msg = static_cast<const dtEntity::TickMessage &>(m);
|
||||
|
||||
for (const auto &comp : mComponents)
|
||||
comp.second->ExecuteCommands(msg.GetSimulationTime());
|
||||
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::PlayerShoot(int32_t id, dtEntity::EntityId shooterid, dtEntity::EntityId targetid,
|
||||
const Vec3d &shooterPos, const Vec3d &targetPos,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst,
|
||||
int lineType, double when, double duration)
|
||||
{
|
||||
ComponentStore::iterator shooter = mComponents.find(shooterid);
|
||||
if (shooter == mComponents.end())
|
||||
return;
|
||||
// targetid may be a building
|
||||
//if (mComponents.find(targetid) == mComponents.end())
|
||||
// return;
|
||||
|
||||
PlayerComponent *shooterc = shooter->second;
|
||||
shooterc->AddCommand(new ShootCommand(when, id, shooterid, targetid, shooterPos, targetPos, buildingIdSrc, roomNumberSrc, buildingIdDst, roomNumberDst, lineType, duration));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::RemovePlayerShoot(int32_t id, double when)
|
||||
{
|
||||
ComponentStore::iterator shooter = mComponents.find(id);
|
||||
if (shooter == mComponents.end())
|
||||
return;
|
||||
|
||||
PlayerComponent *shooterc = shooter->second;
|
||||
shooterc->AddCommand(new RemoveShootCommand(when, id));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::ShowHidePlayer(dtEntity::EntityId eid, bool show, double when)
|
||||
{
|
||||
ComponentStore::iterator i = mComponents.find(eid);
|
||||
if (i != mComponents.end())
|
||||
{
|
||||
PlayerComponent *player = i->second;
|
||||
if (when <= 0)
|
||||
{
|
||||
IconComponent *ic;
|
||||
if (player->GetEntity()->GetComponent(ic))
|
||||
ic->SetVisible(show);
|
||||
}
|
||||
else
|
||||
player->AddCommand(new ShowHidePlayerCommand(when, show));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::TeleportToTarget(dtEntity::EntityId id, double when, const osg::Vec3d &goal, const VCtrl::OBB &obb, int roomNumber, const std::string& roomname)
|
||||
{
|
||||
LOG_DEBUG("PlayerSystem::TeleportToTarget: " << "id='"<< id << "'"
|
||||
<< ", when="<< when
|
||||
<< ", goal: x=" << goal.x() << " y=" << goal.y() << " z=" << goal.z()
|
||||
<< ", roomNumber="<< roomNumber
|
||||
<< ", roomname='"<< roomname << "'");
|
||||
|
||||
ComponentStore::iterator i = mComponents.find(id);
|
||||
if (i != mComponents.end())
|
||||
{
|
||||
PlayerComponent *player = i->second;
|
||||
player->AddCommand(new TeleportToTargetCommand(when, goal, obb, roomNumber, roomname));
|
||||
}
|
||||
else
|
||||
{
|
||||
dtEntityOSG::TransformComponent *pat;
|
||||
if (GetEntityManager().GetComponent(id, pat, true))
|
||||
pat->SetTranslation(goal);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::DeleteQueuedCommands()
|
||||
{
|
||||
for (const auto &comp : mComponents)
|
||||
comp.second->DeleteQueuedCommands();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
#include <dtEntity/scriptaccessor.h>
|
||||
#include <osg/Referenced>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/osgdebugdrawinterface.h>
|
||||
#include "buildingmanager.h"
|
||||
#include <set>
|
||||
|
||||
namespace dtEntityOSG
|
||||
{
|
||||
class TransformComponent;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class PlayerComponent final : public dtEntity::Component
|
||||
{
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
PlayerComponent() = default;
|
||||
|
||||
virtual dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return ((id == TYPE));
|
||||
}
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override;
|
||||
|
||||
void OnRemovedFromEntity(dtEntity::Entity &entity) override;
|
||||
|
||||
dtEntity::Entity *GetEntity() const { return mEntity; }
|
||||
|
||||
void PlaceAt(const osg::Vec3d& _goal, const VCtrl::OBB& obb, int roomNumber, const std::string& roomname);
|
||||
|
||||
struct Command : public osg::Referenced
|
||||
{
|
||||
double mStartTime = 0;
|
||||
Command(double startTime) : mStartTime(startTime) {}
|
||||
virtual ~Command() = default;
|
||||
virtual void Execute(PlayerComponent *component) = 0;
|
||||
};
|
||||
|
||||
void AddCommand(Command *c) { mCommands.insert(c); }
|
||||
size_t GetNumCommands() const { return mCommands.size(); }
|
||||
void ExecuteCommands(double timenow);
|
||||
void DeleteQueuedCommands();
|
||||
|
||||
dtEntityOSG::TransformComponent *GetTransform();
|
||||
|
||||
osg::Vec4 GetColor() const;
|
||||
void SetColor(const osg::Vec4 &);
|
||||
|
||||
dtEntity::StringId GetCurrentCellGroup() const { return mCurrentCellGroup; }
|
||||
dtEntity::StringId GetCurrentRoom() const { return mCurrentRoom; }
|
||||
dtEntity::StringId GetPreviousRoom() const { return mPreviousRoom; }
|
||||
|
||||
private:
|
||||
void PositionOnMesh(const VCtrl::OBB&, osg::Vec3d& pos, const std::string& roomname);
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
|
||||
using Commands = std::set<osg::ref_ptr<Command>>;
|
||||
Commands mCommands;
|
||||
|
||||
dtEntityOSG::TransformComponent *mTransform = nullptr;
|
||||
osg::Vec4f mColor;
|
||||
dtEntity::StringId mCurrentCellGroup = dtEntity::StringId();
|
||||
dtEntity::StringId mCurrentRoom = dtEntity::StringId();
|
||||
dtEntity::StringId mPreviousRoom = dtEntity::StringId();
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class PlayerSystem final
|
||||
: public dtEntity::DefaultEntitySystem<PlayerComponent>
|
||||
, public dtEntity::ScriptAccessor
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
explicit PlayerSystem(dtEntity::EntityManager &em);
|
||||
|
||||
void OnTick(const dtEntity::Message &m);
|
||||
|
||||
void ShowHidePlayer(dtEntity::EntityId eid, bool show, double when);
|
||||
void TeleportToTarget(dtEntity::EntityId id, double when, const osg::Vec3d &goal, const VCtrl::OBB &obb, int roomNumber, const std::string &roomname);
|
||||
void PlayerShoot(int32_t id, dtEntity::EntityId shooterid, dtEntity::EntityId targetid,
|
||||
const Vec3d &shooterPos, const Vec3d &targetPos,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst, int lineType,
|
||||
double when, double duration);
|
||||
void RemovePlayerShoot(int32_t id, double when);
|
||||
|
||||
// delete commands from all players
|
||||
void DeleteQueuedCommands();
|
||||
|
||||
private:
|
||||
dtEntity::MessageFunctor mTickFunctor;
|
||||
};
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
#include "roomdestructioncomponent.h"
|
||||
|
||||
#include "visitors.h"
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <osg/Depth>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Material>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Node>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <sstream>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId RoomDestructionComponent::TYPE(dtEntity::SID("RoomDestruction"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void RoomDestructionComponent::OnEnteredWorld()
|
||||
{
|
||||
|
||||
osg::Shader *vShader = osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("shaders/roomdestruction.vert"));
|
||||
osg::Shader *fShader = osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("shaders/roomdestruction.frag"));
|
||||
|
||||
if (vShader == nullptr || fShader == nullptr)
|
||||
{
|
||||
LOG_ERROR("Could not load building transparency shaders!");
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
osg::Program *p = new osg::Program();
|
||||
p->setName("RoomDestructionShader");
|
||||
p->addShader(vShader);
|
||||
p->addShader(fShader);
|
||||
|
||||
dtEntityOSG::LayerComponent *lc;
|
||||
if (mEntity->GetComponent(lc))
|
||||
{
|
||||
osg::Node *n = lc->GetAttachedComponentNode();
|
||||
if (n != nullptr)
|
||||
{
|
||||
ClearVertexColorsVisitor v;
|
||||
lc->GetAttachedComponentNode()->accept(v);
|
||||
osg::StateSet *ss = n->getOrCreateStateSet();
|
||||
ss->setAttributeAndModes(p);
|
||||
ss->addUniform(new osg::Uniform("room_color", osg::Vec4(1, 1, 1, 1)));
|
||||
ss->addUniform(new osg::Uniform("wall_color", osg::Vec4(1, 1, 1, 1)));
|
||||
}
|
||||
}
|
||||
|
||||
dtEntityOSG::StaticMeshComponent *smc;
|
||||
if (mEntity->GetComponent(smc))
|
||||
{
|
||||
FindRoomNamesVisitor v;
|
||||
smc->GetNode()->accept(v);
|
||||
for (const auto &roomName: v.mNames)
|
||||
mRoomDestructions[roomName] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool RoomDestructionComponent::SetRoomDestructionValue(const std::string &room, float value)
|
||||
{
|
||||
if (mRoomDestructions.find(room) == mRoomDestructions.end())
|
||||
return false;
|
||||
|
||||
FindRoomByNumberVisitor fn;
|
||||
fn.setNameToFind(room);
|
||||
dtEntityOSG::LayerComponent *lc;
|
||||
|
||||
if (!mEntity->GetComponent(lc))
|
||||
return false;
|
||||
|
||||
osg::Node *n = lc->GetAttachedComponentNode();
|
||||
if (n == nullptr)
|
||||
return false;
|
||||
|
||||
lc->GetAttachedComponentNode()->accept(fn);
|
||||
|
||||
|
||||
for (const auto &node : fn.getNodeList())
|
||||
{
|
||||
RoomDestructionSystem *bts;
|
||||
mEntity->GetEntityManager().GetES(bts);
|
||||
|
||||
FindRoomComponentsVisitor frc;
|
||||
node->accept(frc);
|
||||
|
||||
FindExactNameVisitor v(frc.mNamesFound);
|
||||
//LOG_ERROR("Found " + std::to_string(frc.mNamesFound.size()) + " component names");
|
||||
osg::Node *partNode = lc->GetAttachedComponentNode();
|
||||
if (partNode)
|
||||
partNode->accept(v);
|
||||
|
||||
for (const auto &visitedNodes : v.mNodes)
|
||||
{
|
||||
osg::StateSet *ss = visitedNodes->getOrCreateStateSet();
|
||||
ss->addUniform(new osg::Uniform("room_color", osg::Vec4(1, 1 - value, 1 - value, 1)));
|
||||
}
|
||||
}
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(0);
|
||||
|
||||
mRoomDestructions[room] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool RoomDestructionComponent::SetBuildingDestructionValue(float value)
|
||||
{
|
||||
for (const auto &rd : mRoomDestructions)
|
||||
SetRoomDestructionValue(rd.first, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId RoomDestructionSystem::TYPE(dtEntity::SID("RoomDestruction"));
|
||||
|
||||
RoomDestructionSystem::RoomDestructionSystem(dtEntity::EntityManager &em)
|
||||
: dtEntity::DefaultEntitySystem<RoomDestructionComponent>(em)
|
||||
{
|
||||
mEnterWorldFunctor = dtEntity::MessageFunctor(this, &RoomDestructionSystem::OnEnterWorld);
|
||||
em.RegisterForMessages(dtEntity::EntityAddedToSceneMessage::TYPE, mEnterWorldFunctor, "RoomDestructionSystem::OnEnterWorld");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void RoomDestructionSystem::OnEnterWorld(const dtEntity::Message &msg)
|
||||
{
|
||||
dtEntity::EntityId id = msg.Get(dtEntity::EntityAddedToSceneMessage::AboutEntityId)->UIntValue();
|
||||
RoomDestructionComponent *bt;
|
||||
if (GetEntityManager().GetComponent(id, bt))
|
||||
bt->OnEnteredWorld();
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <osgSim/DOFTransform>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class RoomDestructionComponent final : public dtEntity::Component
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return ((id == TYPE));
|
||||
}
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override
|
||||
{
|
||||
mEntity = &entity;
|
||||
}
|
||||
|
||||
void OnEnteredWorld();
|
||||
|
||||
void OnRemovedFromEntity(dtEntity::Entity &) override
|
||||
{
|
||||
mEntity = nullptr;
|
||||
}
|
||||
|
||||
bool SetRoomDestructionValue(const std::string &room, float value);
|
||||
bool SetBuildingDestructionValue(float value);
|
||||
|
||||
using RoomDestructions = std::map<std::string, float>;
|
||||
|
||||
const RoomDestructions &GetRoomDestructions() const
|
||||
{
|
||||
return mRoomDestructions;
|
||||
}
|
||||
private:
|
||||
|
||||
RoomDestructions mRoomDestructions;
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
// iterates over MovementComponents and updates the translation of the entity
|
||||
// after applying forces
|
||||
class RoomDestructionSystem final
|
||||
: public dtEntity::DefaultEntitySystem<RoomDestructionComponent>
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
explicit RoomDestructionSystem(dtEntity::EntityManager &em);
|
||||
void OnEnterWorld(const dtEntity::Message &msg);
|
||||
|
||||
private:
|
||||
|
||||
dtEntity::MessageFunctor mEnterWorldFunctor;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
#include "textcomponent.h"
|
||||
|
||||
|
||||
#include <dtEntity/nodemasks.h>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/LineWidth>
|
||||
#include <osg/Node>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osgText/Text>
|
||||
#include <sstream>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId TextComponent::TYPE(dtEntity::SID("Text"));
|
||||
const dtEntity::StringId TextComponent::PathId(dtEntity::SID("Path"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TextComponent::TextComponent()
|
||||
: dtEntityOSG::TransformComponent(new osg::AutoTransform())
|
||||
, mPath(
|
||||
dtEntity::DynamicStringProperty::SetValueCB(this, &TextComponent::SetText),
|
||||
dtEntity:: DynamicStringProperty::GetValueCB(this, &TextComponent::GetText)
|
||||
)
|
||||
{
|
||||
Register(PathId, &mPath);
|
||||
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->setName("text");
|
||||
tr->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
|
||||
tr->setAutoScaleToScreen(true);
|
||||
tr->setNodeMask(dtEntity::NodeMasks::PICKABLE | dtEntity::NodeMasks::VISIBLE);
|
||||
tr->setNormal(osg::Vec3(0,1,0));
|
||||
osg::StateSet* ss = tr->getOrCreateStateSet();
|
||||
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
ss->setRenderBinDetails(90, "DepthSortedBin");
|
||||
ss->setMode(GL_BLEND,osg::StateAttribute::ON);
|
||||
ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
osg::ref_ptr<osg::LineWidth> lw = new osg::LineWidth();
|
||||
lw->setWidth(2);
|
||||
ss->setAttributeAndModes(lw, osg::StateAttribute::ON);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::Rebuild()
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->dirtyBound();
|
||||
tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 10));
|
||||
tr->removeChildren(0, tr->getNumChildren());
|
||||
|
||||
if(!mVisible) return;
|
||||
|
||||
osg::ref_ptr<osg::Geode> g = new osg::Geode();
|
||||
tr->addChild(g);
|
||||
tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 1));
|
||||
|
||||
osgText::Text* text = new osgText::Text();
|
||||
text->setBackdropType(osgText::Text::NONE);
|
||||
text->setCharacterSize(20);
|
||||
text->setCharacterSizeMode(osgText::TextBase::SCREEN_COORDS);
|
||||
//text->setColor(color);
|
||||
if(mDisText.empty())
|
||||
{
|
||||
text->setText(mText);
|
||||
}
|
||||
else
|
||||
{
|
||||
text->setText(mDisText);
|
||||
}
|
||||
text->setAlignment(osgText::TextBase::CENTER_CENTER);
|
||||
text->setAxisAlignment(osgText::TextBase::SCREEN);
|
||||
//text->setPosition(position);
|
||||
osg::StateSet* ss = text->getOrCreateStateSet();
|
||||
osg::PolygonMode* polyModeObj = new osg::PolygonMode;
|
||||
polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL);
|
||||
ss->setAttribute(polyModeObj);
|
||||
|
||||
g->addDrawable(text);
|
||||
|
||||
if(mSelected)
|
||||
{
|
||||
int x, y, w, h;
|
||||
int b = 6;
|
||||
x = -25 / 2 - b;
|
||||
y = 0 - b;
|
||||
w = 25 + b * 2;
|
||||
h = 4 + b * 2;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> sel = new osg::Geometry();
|
||||
g->addDrawable(sel);
|
||||
osg::Vec4Array* colours = new osg::Vec4Array(1);
|
||||
(*colours)[0] = osg::Vec4(1,0,0,1);
|
||||
sel->setColorArray(colours);
|
||||
sel->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
osg::Vec3Array* coords = new osg::Vec3Array(4);
|
||||
(*coords)[0] = osg::Vec3(x , y , 0);
|
||||
(*coords)[1] = osg::Vec3(x , y + h, 0);
|
||||
(*coords)[2] = osg::Vec3(x + w, y + h, 0);
|
||||
(*coords)[3] = osg::Vec3(x + w, y , 0);
|
||||
sel->setVertexArray(coords);
|
||||
sel->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, 4));
|
||||
osg::ref_ptr<osg::PolygonMode> p = new osg::PolygonMode;
|
||||
p->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
|
||||
sel->getOrCreateStateSet()->setAttribute(p);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string TextComponent::GetText() const
|
||||
{
|
||||
return mText;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetText(const std::string& text)
|
||||
{
|
||||
if(mText != text)
|
||||
{
|
||||
mText = text;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string TextComponent::GetDisText() const
|
||||
{
|
||||
return mDisText;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetDisText(const std::string& text)
|
||||
{
|
||||
if(mDisText != text)
|
||||
{
|
||||
mDisText = text;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Vec3d TextComponent::GetTranslation() const
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
return tr->getPosition();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetTranslation(const dtEntity::Vec3d& v)
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->setPosition(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Vec3d TextComponent::GetScale() const
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
return tr->getScale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetScale(const dtEntity::Vec3d& v)
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->setScale(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Quat TextComponent::GetRotation() const
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
return tr->getRotation();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetRotation(const dtEntity::Quat& v)
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->setRotation(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetColor(const osg::Vec4& v)
|
||||
{
|
||||
if(mColor != v)
|
||||
{
|
||||
mColor = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TextComponent::GetShowSelection() const
|
||||
{
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetShowSelection(bool v)
|
||||
{
|
||||
//if(mSelected != v)
|
||||
{
|
||||
mSelected = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetVisible(bool v)
|
||||
{
|
||||
//if(mVisible != v)
|
||||
{
|
||||
mVisible = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
TextSystem::TextSystem(dtEntity::EntityManager& em)
|
||||
: dtEntity::DefaultEntitySystem<TextComponent>(em, dtEntityOSG::TransformComponent::TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntityOSG/nodecomponent.h>
|
||||
#include <osg/AutoTransform>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class TextComponent final : public dtEntityOSG::TransformComponent
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
static const dtEntity::StringId PathId;
|
||||
|
||||
|
||||
TextComponent();
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return ((id == TYPE));
|
||||
}
|
||||
|
||||
std::string GetText() const;
|
||||
void SetText(const std::string& text);
|
||||
|
||||
std::string GetDisText() const;
|
||||
void SetDisText(const std::string& text);
|
||||
|
||||
osg::Vec4 GetColor() const { return mColor; }
|
||||
void SetColor(const osg::Vec4&);
|
||||
|
||||
dtEntity::Vec3d GetTranslation() const override;
|
||||
void SetTranslation(const dtEntity::Vec3d&) override;
|
||||
|
||||
dtEntity::Vec3d GetScale() const override;
|
||||
void SetScale(const dtEntity::Vec3d&) override;
|
||||
|
||||
dtEntity::Quat GetRotation() const override;
|
||||
void SetRotation(const dtEntity::Quat&) override;
|
||||
|
||||
bool GetShowSelection() const;
|
||||
void SetShowSelection(bool v);
|
||||
|
||||
void SetVisible(bool v);
|
||||
bool GetVisible() const { return mVisible; }
|
||||
|
||||
private:
|
||||
|
||||
void Rebuild();
|
||||
|
||||
dtEntity::DynamicStringProperty mPath;
|
||||
|
||||
std::string mText;
|
||||
std::string mDisText;
|
||||
osg::Vec4 mColor;
|
||||
bool mSelected = false;
|
||||
bool mVisible = false;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
// iterates over MovementComponents and updates the translation of the entity
|
||||
// after applying forces
|
||||
class TextSystem final
|
||||
: public dtEntity::DefaultEntitySystem<TextComponent>
|
||||
{
|
||||
|
||||
public:
|
||||
explicit TextSystem(dtEntity::EntityManager& em);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "videocomponent.h"
|
||||
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/stringid.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include "windowcapturecallback.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId VideoSystem::TYPE(dtEntity::SID("Video"));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool VideoSystem::StartVideoRecording(unsigned int contextid, const std::string &path, int w, int h, int framerate, int quality)
|
||||
{
|
||||
if (mWindowCaptureCallback.valid())
|
||||
{
|
||||
LOG_ERROR("Cannot start video recording, already started!");
|
||||
return false;
|
||||
}
|
||||
StopVideoRecording(contextid);
|
||||
|
||||
dtEntityOSG::CameraSystem *cs;
|
||||
GetEntityManager().GetES(cs);
|
||||
|
||||
dtEntity::EntityId camid = cs ? cs->GetCameraEntityByContextId(contextid) : 0;
|
||||
|
||||
dtEntityOSG::CameraComponent *camcomp;
|
||||
if (camid == 0 || !GetEntityManager().GetComponent(camid, camcomp))
|
||||
{
|
||||
LOG_ERROR("Cannot set up video stream, camera not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
mWindowCaptureCallback = new WindowCaptureCallback(GL_BACK, contextid, path, w, h, framerate, quality);
|
||||
|
||||
camcomp->GetCamera()->setFinalDrawCallback(mWindowCaptureCallback);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool VideoSystem::StopVideoRecording(unsigned int contextid)
|
||||
{
|
||||
if (mWindowCaptureCallback.valid())
|
||||
{
|
||||
dtEntityOSG::CameraSystem *camsys;
|
||||
if (GetEntityManager().GetES(camsys))
|
||||
{
|
||||
dtEntity::EntityId camid = camsys->GetCameraEntityByContextId(contextid);
|
||||
if (camid != 0)
|
||||
{
|
||||
dtEntityOSG::CameraComponent *cam;
|
||||
if (GetEntityManager().GetComponent(camid, cam))
|
||||
cam->GetCamera()->setFinalDrawCallback(nullptr);
|
||||
}
|
||||
}
|
||||
mWindowCaptureCallback = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntity/property.h>
|
||||
#include <dtEntity/debugdrawinterface.h>
|
||||
#include "windowcapturecallback.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class VideoSystem final
|
||||
: public dtEntity::EntitySystem
|
||||
{
|
||||
using BaseClass = dtEntity::EntitySystem;
|
||||
|
||||
public:
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
|
||||
using dtEntity::EntitySystem::EntitySystem;
|
||||
|
||||
dtEntity::ComponentType GetComponentType() const override { return TYPE; }
|
||||
|
||||
bool StartVideoRecording(unsigned int contextid, const std::string &path, int w, int h, int framerate, int quality);
|
||||
bool StopVideoRecording(unsigned int contextid);
|
||||
|
||||
private:
|
||||
|
||||
osg::ref_ptr<WindowCaptureCallback> mWindowCaptureCallback;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,695 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <QJsonValue>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <exccommands.h>
|
||||
|
||||
class QWidget;
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
using Timer_t = __int64;
|
||||
#else
|
||||
using Timer_t = unsigned long long;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Class representing 2-dimensional float vector
|
||||
*/
|
||||
struct Vec2
|
||||
{
|
||||
Vec2() = default;
|
||||
Vec2(float _x, float _y) : x(_x) , y(_y) { }
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing 3-dimensional float vector
|
||||
*/
|
||||
struct Vec3
|
||||
{
|
||||
Vec3() = default;
|
||||
Vec3(float _x, float _y, float _z) : x(_x) , y(_y) , z(_z) { }
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing 3-dimensional double vector
|
||||
*/
|
||||
struct Vec3d
|
||||
{
|
||||
Vec3d() = default;
|
||||
Vec3d(double _x, double _y, double _z) : x(_x) , y(_y) , z(_z) { }
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing a color value.
|
||||
* Colors are encoded with 0.0 - 1.0 values for each channel.
|
||||
* w component represents alpha / transparency.
|
||||
*/
|
||||
|
||||
struct Color
|
||||
{
|
||||
Color() = default;
|
||||
Color(float _x, float _y, float _z, float _w) : x(_x) , y(_y) , z(_z) , w(_w) { }
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
float w = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing a quaternion.
|
||||
* Used for representing rotations.
|
||||
*/
|
||||
struct Quat
|
||||
{
|
||||
Quat() = default;
|
||||
Quat(double _x, double _y, double _z, double _w) : x(_x) , y(_y) , z(_z) , w(_w) { }
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
double w = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* How to treat the z value
|
||||
*/
|
||||
enum class ZValue
|
||||
{
|
||||
AboveMsl, //!< treat z as above msl
|
||||
RelativeBuildings, //!< the z position is relative to the buildings
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumerates view modes for 2d building displays
|
||||
*/
|
||||
enum class ViewMode
|
||||
{
|
||||
ISOMETRIC,
|
||||
ORTHOGRAPHIC
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumerates view modes for 2d building displays
|
||||
*/
|
||||
enum class PlayerDisplayMode
|
||||
{
|
||||
Icons,
|
||||
Dots
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback class for receiving events from viewer side.
|
||||
* Use with ViewerInterface::SetViewerCallback()
|
||||
*/
|
||||
class ViewerCallback
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ViewerCallback() = default;
|
||||
|
||||
/**
|
||||
* Gets called when building position map has finished loading and
|
||||
* system is ready for use
|
||||
*/
|
||||
virtual void SystemReady() = 0;
|
||||
|
||||
/**
|
||||
* Gets called when the position of an entity has changed
|
||||
* @param id Id of moving entity
|
||||
* @param pos Position of entity relative to terrain origin in meters
|
||||
* @param attitude rotation of entity relative to posititive y axis
|
||||
*/
|
||||
virtual void TransformChanged(const std::string &id, const Vec3d &pos, const Quat &attitude) = 0;
|
||||
|
||||
/**
|
||||
* Gets called when entity moves from one navmesh group (building or outside mesh)
|
||||
* to the next
|
||||
* @param id Id of moving entity
|
||||
* @param grpname Name of navmesh group
|
||||
*/
|
||||
virtual void NavMeshGroupChanged(const std::string &id, const std::string &grpname) = 0;
|
||||
|
||||
/**
|
||||
* Player has clicked on an entity symbol with the left mouse button.
|
||||
* @param id Id of picked entity
|
||||
*/
|
||||
virtual void PlayerPicked(const std::string &id) = 0;
|
||||
|
||||
/**
|
||||
* Player has clicked on an displayName with the left mouse button.
|
||||
* @param buildingid Id of picked entity
|
||||
* @param roomname roomname of picked entity
|
||||
*/
|
||||
virtual void DisplayNamePicked(const std::string& buildingid, const std::string& roomname) = 0;
|
||||
|
||||
/**
|
||||
* A building view was opened.
|
||||
* @param contextId id of graphics context. Can be used to close the view.
|
||||
* @param viewmode Initial view mode of view
|
||||
*/
|
||||
virtual void ViewCreated(unsigned int contextId, ViewMode viewmode) = 0;
|
||||
|
||||
/**
|
||||
* View mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::ChangeViewMode or a click on the view mode buttons in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param viewmode New view mode of view
|
||||
*/
|
||||
virtual void ViewModeChanged(unsigned int contextId, ViewMode viewmode) = 0;
|
||||
|
||||
/**
|
||||
* Line mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::ChangeLineMode or a click on the line mode buttons in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param line Is line on or off
|
||||
*/
|
||||
virtual void ViewLineModeChanged(unsigned int contextId, bool line) = 0;
|
||||
|
||||
/**
|
||||
* Name mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::ChangeNameMode or a click on the name mode buttons in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param name Is name on or off
|
||||
*/
|
||||
virtual void ViewNameModeChanged(unsigned int contextId, bool name) = 0;
|
||||
|
||||
/**
|
||||
* Lock ViewTransparencyChanged mode of view was changed. Triggered by slider
|
||||
*/
|
||||
virtual void ViewTransparencyChanged() = 0;
|
||||
|
||||
/**
|
||||
* Lock Rotation mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::LockViewRotationToMapRotation or a click on
|
||||
* the lock checkbox in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param lock Is lock on or off
|
||||
*/
|
||||
virtual void ViewLockRotationChanged(unsigned int contextId, bool lock) = 0;
|
||||
|
||||
/**
|
||||
* Player display mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::SetViewerDisplayMode or a click on
|
||||
* the display mode checkbox in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param mode Mode enumerator
|
||||
*/
|
||||
virtual void PlayerDisplayModeChanged(unsigned int contextId, PlayerDisplayMode mode) = 0;
|
||||
|
||||
/**
|
||||
* View was closed via ViewerInterface::CloseView or click on window
|
||||
* close GUI element
|
||||
* @param contextId id of graphics context.
|
||||
*/
|
||||
virtual void ViewClosed(unsigned int contextId) = 0;
|
||||
|
||||
virtual void HandleViewerEvent(BuildingViewer::BgViewerEvents event,
|
||||
const std::vector<std::string> &args) = 0;
|
||||
virtual void ViewZoomChanged(const std::string &buildingId,
|
||||
double top, double left, double bottom, double right) = 0;
|
||||
|
||||
enum class Severity
|
||||
{
|
||||
Always,
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal
|
||||
};
|
||||
/**
|
||||
* Receives error and other log messages from viewer
|
||||
* @param severity The severity of the message
|
||||
* @param filename The file that the log command was called from
|
||||
* @param methodname The name of the method containing the log command
|
||||
* @param linenumber The line number the log command was issued from
|
||||
* @param msg Text of the log message
|
||||
*/
|
||||
virtual void LogMessage(Severity &severity, const std::string &filename,
|
||||
const std::string &methodname,
|
||||
int linenumber, const std::string &msg) = 0;
|
||||
|
||||
};
|
||||
|
||||
class ViewerInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ViewerInterface() = default;
|
||||
|
||||
/**
|
||||
* Register object for receiving viewer event callbacks
|
||||
*/
|
||||
virtual void SetViewerCallback(ViewerCallback *) = 0;
|
||||
virtual void RemoveViewerCallback() = 0;
|
||||
|
||||
/**
|
||||
* Is used to set location of project specific terrain and building data.
|
||||
* Example: "/home/martin/ProjectAssetsBremen"
|
||||
*/
|
||||
virtual void SetProjectDataPaths(const std::vector<std::string> &paths) = 0;
|
||||
|
||||
/**
|
||||
* Open 3d view of whole terrain - for debugging purposes only!
|
||||
*/
|
||||
virtual void OpenOverview() = 0;
|
||||
|
||||
virtual QWidget* getMainWindow() = 0;
|
||||
virtual quintptr requestMainWindowHandle() = 0;
|
||||
|
||||
virtual void reloadPlayerIcons() = 0;
|
||||
virtual void UpdatePlayerPartyColors(const std::map<std::string, VCtrl::Color>& mapPlayerColors) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief true if positioningsystem gets exact position of player. Will be used for all opened views (GLOBAL FLAG)
|
||||
* @param exactPos
|
||||
*/
|
||||
virtual void UseExactPositioning(bool exactPos) = 0;
|
||||
|
||||
/**
|
||||
* Open a new display showing the building identified by buildingid.
|
||||
* @param buildingid ID of the building. Use GetBuildingIds() to get all building ids
|
||||
* @param windowtitle Title to display on window top
|
||||
* @param bgcolor Background color of window
|
||||
* @param viewmode The perspective mode to show building in
|
||||
* @param screennum Number of screen to open display on
|
||||
* @param fullscreen Ignore width and position and display as fullscreen instead
|
||||
* @param x X-Position of window
|
||||
* @param y Y-Position of window
|
||||
* @param width Width of display in pixels
|
||||
* @param height Height of display in pixels
|
||||
* @param contextId receives context ID of the new view. Use it to close the view programmatically.
|
||||
* @param exactPos true if positioningsystem gets exact position of player
|
||||
* @return true if success
|
||||
*/
|
||||
virtual bool OpenView(const std::string &buildingid, const std::string &windowtitle, const Color &bgcolor, ViewMode viewmode,
|
||||
int screennum, bool fullscreen, int x, int y, int width, int height,
|
||||
unsigned int &contextId, bool exactPos = true) = 0;
|
||||
virtual void openViews(const std::vector<std::string> &bldIds, bool exactPos) = 0;
|
||||
|
||||
/**
|
||||
* Is a certain view opened?
|
||||
* @param bldId ID of the building.
|
||||
*/
|
||||
virtual bool isViewOpen(const std::string &bldId) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Close display previously opened with OpenView
|
||||
* @param contextid context id of view, as returned from OpenView()
|
||||
*/
|
||||
virtual void CloseView(unsigned int contextid) = 0;
|
||||
virtual void closeViews(const std::vector<std::string> &bldIds) = 0;
|
||||
|
||||
/**
|
||||
* Change view mode of an existing view.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param viewmode Viewmode enum value
|
||||
*/
|
||||
virtual void ChangeViewMode(unsigned int contextId, ViewMode viewmode) = 0;
|
||||
virtual void setViewMode(ViewMode m) = 0;
|
||||
|
||||
/**
|
||||
* Change view mode of an existing view.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param line true if view should show lines outside , false if not
|
||||
*/
|
||||
virtual void ChangeLineMode(unsigned int contextId, bool line) = 0;
|
||||
|
||||
/**
|
||||
* Change view mode of an existing view.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param name true if view should show names, false if not
|
||||
*/
|
||||
virtual void ChangeNameMode(unsigned int contextId, bool name) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Set if view should rotate in accord with map rotation
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param lock true if view should rotate, false if it should remain static
|
||||
*/
|
||||
virtual void LockViewRotationToMapRotation(unsigned int contextId, bool lock) = 0;
|
||||
|
||||
/**
|
||||
* Set if view should display movable players as dots or as icons
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param mode Display mode enumerator
|
||||
*/
|
||||
virtual void SetPlayerDisplayMode(unsigned int contextId, PlayerDisplayMode mode) = 0;
|
||||
virtual void setDisplayMode(PlayerDisplayMode m) = 0;
|
||||
|
||||
/**
|
||||
* Set wall transparency for a building window.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param transparency 0 equals opaque, 1 equals invisible
|
||||
*/
|
||||
virtual void SetWallTransparency(unsigned int contextId, float transparency) = 0;
|
||||
virtual void setTransparency(double percent) = 0;
|
||||
|
||||
/**
|
||||
* All views with "LockViewRotationToMapRotation" enabled will rotate their camera
|
||||
* to have a camera angle looking towards north, rotated by input angle.
|
||||
* @returnRotation angle in degrees from north CCW
|
||||
*/
|
||||
virtual float GetMapRotation() const = 0;
|
||||
|
||||
/**
|
||||
* All views with "LockViewRotationToMapRotation" enabled will rotate their camera
|
||||
* to have a camera angle looking towards north, rotated by input angle.
|
||||
* @param angle Rotation angle in degrees from north CCW
|
||||
*/
|
||||
virtual void SetMapRotation(float angle) = 0;
|
||||
|
||||
/**
|
||||
* add buildings to scene and recalculate navigation meshes
|
||||
* @param path Load map from this path. example: "Projections/data.xml"
|
||||
*/
|
||||
virtual bool LoadBuildingPositionMap(const std::string &path, bool loadAllAvailableBuildings) = 0;
|
||||
|
||||
/**
|
||||
* Create new player at (0,0,0). Player is initially invisible!
|
||||
* @param id a unique string that can later be used to reference the player
|
||||
* @param iconpath system file path to player icon. Can be relative to ProjectAssets folder root.
|
||||
* @param color Initial color of the player
|
||||
*/
|
||||
virtual void CreatePlayer(const std::string &id, const std::string &iconpath, const Color &color) = 0;
|
||||
|
||||
/**
|
||||
* Delete player with given id
|
||||
* @param seconds Delete player n seconds from now
|
||||
*/
|
||||
virtual void DeletePlayer(const std::string &id, float seconds = 0) = 0;
|
||||
|
||||
/**
|
||||
* This color is added to the player texture color.
|
||||
*/
|
||||
virtual void SetPlayerColor(const std::string &id, const Color &color) = 0;
|
||||
|
||||
/**
|
||||
* Set icon path for existing player
|
||||
* @param path system file path to player icon. Can be relative to ProjectAssets folder root.
|
||||
* If path is to current icon path then icon is reloaded from file.
|
||||
*/
|
||||
virtual void SetPlayerIcon(const std::string &id, const std::string &path) = 0;
|
||||
|
||||
/**
|
||||
* Return number of soldier instances
|
||||
*/
|
||||
virtual size_t GetNumPlayers() const = 0;
|
||||
|
||||
/**
|
||||
* Fill vector with ids of all existing players
|
||||
*/
|
||||
virtual void GetPlayerIds(std::vector<std::string> &toFill) = 0;
|
||||
|
||||
/**
|
||||
* Hide or unhide player with given id
|
||||
* @param show true to show, false to hide
|
||||
* @param when simulation time when show or hide should be executed - < 0 --> show immediatelly
|
||||
*/
|
||||
virtual void SetPlayerShown(const std::string &id, bool show, double when = -1) = 0;
|
||||
|
||||
/**
|
||||
* Return number of building instances
|
||||
*/
|
||||
virtual size_t GetNumBuildings() const = 0;
|
||||
|
||||
/**
|
||||
* Fill vector with ids of all existing buildings
|
||||
*/
|
||||
virtual void GetBuildingIds(std::vector<std::string> &toFill) const = 0;
|
||||
|
||||
/**
|
||||
* Add or remove visible bounding box around entity
|
||||
* @param id unique id of entity
|
||||
* @param show set true to show box, false to make invisible
|
||||
* @param duration If non-negative, remove box after duration seconds
|
||||
*/
|
||||
virtual void SetShowSelectionBox(const std::string &id,
|
||||
bool show,
|
||||
float duration = -1) = 0;
|
||||
|
||||
/**
|
||||
* Add a line from start to end
|
||||
* Line is deleted after duration seconds.
|
||||
* If duration is 0 then line is never deleted
|
||||
*/
|
||||
virtual void Shoot(const int id,
|
||||
const std::string &shooterId,
|
||||
const std::string &targetId,
|
||||
const Vec3d &shooterPos,
|
||||
const Vec3d &targetPos,
|
||||
int buildingIdSrc,
|
||||
int roomNumberSrc,
|
||||
int buildingIdDst,
|
||||
int roomNumberDst,
|
||||
int lineType,
|
||||
double when) = 0;
|
||||
|
||||
/**
|
||||
* Add a line from start to end where end is a room in the given building
|
||||
* Line is deleted after duration seconds.
|
||||
* If duration is 0 then line is never deleted
|
||||
*/
|
||||
virtual void Shoot(const int id,
|
||||
const std::string &shooterId,
|
||||
const std::string &targetBuildingId,
|
||||
const std::string &targetRoomId,
|
||||
const Vec3d &shooterPos,
|
||||
int lineType,
|
||||
double when) = 0;
|
||||
|
||||
/**
|
||||
* Remove a line
|
||||
*/
|
||||
virtual void removeShoot(const int id) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Directly move player to target position, do not use pathfinding. Cancels current path following activity.
|
||||
* @param id Id of player
|
||||
* @param when Simulation time when teleport should happen
|
||||
* @param target position to teleport to
|
||||
* @param bldgname name of building containing position, empty string to ignore
|
||||
* @param roomname name of room containing position, empty string to ignore
|
||||
*/
|
||||
virtual void Teleport(const std::string &id,
|
||||
double when,
|
||||
const Vec3d &target,
|
||||
const std::string &bldgname,
|
||||
int roomNumber,
|
||||
const std::string &roomname,
|
||||
ZValue zval) = 0;
|
||||
/**
|
||||
* Get names of all rooms in building
|
||||
* @param id Id of building player
|
||||
* @param names will be filled with room names
|
||||
*/
|
||||
virtual void GetRoomNames(const std::string &id, std::vector<std::string> &names) = 0;
|
||||
|
||||
/**
|
||||
* Sets destruction value for room of a building.
|
||||
* @param id Id of building player
|
||||
* @param roomnumber number of room to set (ex: "2001")
|
||||
* @param value destruction value. 0: not destroyed, 1: fully destroyed
|
||||
* @return true if room was found
|
||||
*/
|
||||
virtual bool SetRoomDestructionValue(const std::string &id,
|
||||
const std::string &roomname,
|
||||
float value) = 0;
|
||||
|
||||
/**
|
||||
* Sets destruction value for all rooms of a building.
|
||||
* @param id Id of building player
|
||||
* @param value destruction value. 0: not destroyed, 1: fully destroyed
|
||||
* @return true if room was found
|
||||
*/
|
||||
virtual bool SetBuildingDestructionValue(const std::string &id, float value) = 0;
|
||||
|
||||
/**
|
||||
* Get names of all cameras, loudspeakers and other devices in building
|
||||
* @param buildingid Id of building player
|
||||
* @param names will be filled with device names
|
||||
*/
|
||||
virtual void GetDeviceNames(const std::string &buildingid, std::vector<std::string> &names) = 0;
|
||||
|
||||
/**
|
||||
* Show an icon at center position of device node
|
||||
* @param id unique id for entity that can be used to hide it at a later point
|
||||
* @param buildingid id of building containing the device
|
||||
* @param devicename name of device node to show icon at
|
||||
* @param iconpath absolute path to icon to show at device position
|
||||
* @return true if device was found in building
|
||||
*/
|
||||
virtual bool ShowDeviceIcon(const std::string &id, const std::string &buildingid,
|
||||
const std::string &devicename, const std::string &iconpath) = 0;
|
||||
|
||||
/**
|
||||
* Show an icon at center position of device node
|
||||
* @param id unique id for entity that can be used to hide it at a later point
|
||||
* @param buildingid id of building containing the device
|
||||
* @param position Position of camera relative to building
|
||||
* @param iconpath absolute path to icon to show at device position
|
||||
* @return true if device was found in building
|
||||
*/
|
||||
virtual bool ShowDeviceIcon(const std::string &id, const std::string &buildingid,
|
||||
const Vec3d &position, const std::string &iconpath) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Hide device icon created with ShowDevice
|
||||
* @param id Id used in call to ShowDevice
|
||||
* @return true if device entity was found and successfully removed
|
||||
*/
|
||||
virtual bool HideDeviceIcon(const std::string &id) = 0;
|
||||
|
||||
/**
|
||||
* Set the displayName of the given room in a given building
|
||||
* @param buildingid id of building
|
||||
* @param roomname
|
||||
* @param strDisplayName
|
||||
* @return true if room was found in building
|
||||
*/
|
||||
virtual bool SetDisplayName(const std::string& buildingid, const std::string& roomname,
|
||||
const std::string& strDisplayName) = 0;
|
||||
|
||||
/**
|
||||
* Show the displayName in a given building
|
||||
* @param buildingid id of building
|
||||
* @param show set true to show displayNames, false to make invisible
|
||||
*/
|
||||
virtual void ShowDisplayNames(const std::string& buildingid, bool show) = 0;
|
||||
|
||||
/**
|
||||
* Add or remove visible bounding box around displayName entity
|
||||
* @param buildingid unique id of building
|
||||
* @param id id of room
|
||||
* @param show set true to show box, false to make invisible
|
||||
* @param duration If non-negative, remove box after duration seconds
|
||||
*/
|
||||
virtual void SetShowDisplayNamesSelectionBox(const std::string& buildingid,
|
||||
const std::string& id,
|
||||
bool show,
|
||||
float duration = -1) = 0;
|
||||
|
||||
/**
|
||||
* Get time scale. Scale 1 is normal, scale 2 is double normal speed
|
||||
*/
|
||||
virtual float GetTimeScale() const = 0;
|
||||
|
||||
/**
|
||||
* Scale time. Scale 1 is normal, scale 2 is double normal speed
|
||||
*/
|
||||
virtual void SetTimeScale(float scale) = 0;
|
||||
|
||||
/**
|
||||
* Set current simulation time in seconds
|
||||
*/
|
||||
virtual void SetSimulationTime(double t) = 0;
|
||||
|
||||
/**
|
||||
* Get current simulation time in seconds
|
||||
*/
|
||||
virtual double GetSimulationTime() const = 0;
|
||||
|
||||
/**
|
||||
* Pause simulation time and all events
|
||||
*/
|
||||
virtual void SetPaused(bool) = 0;
|
||||
virtual bool GetPaused() const = 0;
|
||||
|
||||
/**
|
||||
* Switch on or off non realtime mode.
|
||||
* Non realtime mode is used for recording videos at faster than real time speed.
|
||||
* Frames are rendered and compressed as fast as possible, simulation time
|
||||
* does not correspond to real time.
|
||||
*/
|
||||
virtual void SetNonRealtimeMode(bool on) = 0;
|
||||
|
||||
/**
|
||||
* Is non-realtime mode on or off?
|
||||
*/
|
||||
virtual bool GetNonRealtimeMode() const = 0;
|
||||
|
||||
/**
|
||||
* Advance simulation until given simulation time is reached
|
||||
*/
|
||||
virtual void FastForwardSimulationTo(double t) = 0;
|
||||
|
||||
/**
|
||||
* Remove all queued commands for soldiers
|
||||
*/
|
||||
virtual void DeleteQueuedCommands() = 0;
|
||||
|
||||
/**
|
||||
* Start recording an mpeg video of the view.
|
||||
* @param contextid context id of the view to record.
|
||||
* @param path Record to this file. Extension should be .mpg
|
||||
* @param w width of recorded video file (input is rescaled)
|
||||
* @param h height of recorded video file (input is rescaled)
|
||||
* @param framerate frames per second to record. Reasonable value: 15 - 30
|
||||
* @param quality Compression quality in percent.
|
||||
*/
|
||||
virtual bool StartVideoRecording(unsigned int contextid, const std::string &path,
|
||||
int w, int h, int framerate, int quality) = 0;
|
||||
virtual bool StartVideoRecording(const std::string &buildingId, const std::string &path,
|
||||
int w, int h, int framerate, int quality) = 0;
|
||||
|
||||
/**
|
||||
* Stop recording
|
||||
* @param contextid context id of the view to record.
|
||||
*/
|
||||
virtual bool StopVideoRecording(unsigned int contextid) = 0;
|
||||
virtual bool StopVideoRecording(const std::string &buildingId) = 0;
|
||||
|
||||
|
||||
virtual QJsonValue getViewState() const = 0;
|
||||
virtual void setViewState(const QJsonValue &val) = 0;
|
||||
virtual void highlightView(const std::string &buildingId) = 0;
|
||||
virtual void setBuildingDisplayName(const std::string &buildingId, const std::string &displayName) = 0;
|
||||
|
||||
virtual void setHitLineDuration(uint32_t durationSec) = 0;
|
||||
struct MountingPointDescription
|
||||
{
|
||||
std::string buildingId;
|
||||
std::string mountingPointId;
|
||||
Vec3d position;
|
||||
BuildingViewer::AssetTypes assetType;
|
||||
};
|
||||
virtual void setMountingPointAsset(const MountingPointDescription &asset) = 0;
|
||||
|
||||
struct BuildingState
|
||||
{
|
||||
std::string buildingId;
|
||||
std::string description;
|
||||
int entityId = 0;
|
||||
bool isShown = false;
|
||||
};
|
||||
virtual std::vector<BuildingState> getBuildingState() const = 0;
|
||||
};
|
||||
}
|
||||
+2344
File diff suppressed because it is too large.
Load diff
+524
@@ -0,0 +1,524 @@
|
||||
#pragma once
|
||||
|
||||
#include "viewerinterface.h"
|
||||
#include "viewwidgetcontainer.h"
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <dtEntityOSG/osgsysteminterface.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <osg/io_utils>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include "buildingmanager.h"
|
||||
#include "exccommands.h"
|
||||
#include "viewwidgetstate.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace dtEntity
|
||||
{
|
||||
class EntityManager;
|
||||
class MapSystem;
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class PlayerSystem;
|
||||
class BuildingManager;
|
||||
class ViewWidget;
|
||||
class LogHandler;
|
||||
|
||||
class CtrlMainWindow;
|
||||
|
||||
class CtrlImpl : public QObject, public ViewerInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
CtrlImpl(dtEntity::EntityManager &em, QWidget *parentWidget);
|
||||
~CtrlImpl();
|
||||
|
||||
void SetViewerCallback(ViewerCallback *) override;
|
||||
void RemoveViewerCallback() override;
|
||||
|
||||
/**
|
||||
* Is used to set location of project specific terrain and building data.
|
||||
* Example: "/home/martin/ProjectAssetsBremen"
|
||||
*/
|
||||
void SetProjectDataPaths(const std::vector<std::string> &paths) override;
|
||||
|
||||
QWidget* getMainWindow() override;
|
||||
quintptr requestMainWindowHandle() override;
|
||||
|
||||
|
||||
void openViews(const std::vector<std::string> &bldIds, bool exactPos) override;
|
||||
bool isViewOpen(const std::string &strBldId) const override;
|
||||
|
||||
void closeViews(const std::vector<std::string> &vecFeatureIDs) override;
|
||||
void closeAllViews();
|
||||
|
||||
void UseExactPositioning(bool exactPos) override;
|
||||
|
||||
/**
|
||||
* Open a new display showing the building identified by buildingid.
|
||||
* @param buildingid ID of the building. Use GetBuildingIds() to get all building ids
|
||||
* @param windowtitle Title to display on window top
|
||||
* @param bgcolor Window background color
|
||||
* @param viewmode The perspective mode to show building in
|
||||
* @param screennum Number of screen to open display on
|
||||
* @param fullscreen Ignore width and position and display as fullscreen instead
|
||||
* @param x X-Position of window
|
||||
* @param y Y-Position of window
|
||||
* @param width Width of display in pixels
|
||||
* @param height Height of display in pixels
|
||||
* @param contextId receives context ID of the new view. Use it to close the view programmatically.
|
||||
* @param exactPos true if positioningsystem gets exact position of player
|
||||
* @return true if success
|
||||
*/
|
||||
bool OpenView(const std::string &buildingid, const std::string &windowtitle, const Color &col,
|
||||
ViewMode viewmode, int screennum,
|
||||
bool fullscreen, int x, int y, int w, int h, unsigned int &contextid, bool exactPos = true) override;
|
||||
|
||||
|
||||
/**
|
||||
* Close display previously opened with OpenView
|
||||
* @param contextid context id of view, as returned from OpenView()
|
||||
*/
|
||||
void CloseView(unsigned int contextid) override;
|
||||
|
||||
/**
|
||||
* Change view mode of an existing view.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param viewmode Viewmode enum value
|
||||
*/
|
||||
void ChangeViewMode(unsigned int contextId, ViewMode viewmode) override;
|
||||
|
||||
/**
|
||||
* Set if view should rotate in accord with map rotation
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param lock true if view should rotate, false if it should remain static
|
||||
*/
|
||||
void LockViewRotationToMapRotation(unsigned int contextId, bool lock) override;
|
||||
|
||||
/**
|
||||
* Set if view should display movable players as dots or as icons
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param mode Display mode enumerator
|
||||
*/
|
||||
void SetPlayerDisplayMode(unsigned int contextId, PlayerDisplayMode mode) override;
|
||||
|
||||
/**
|
||||
* Set wall transparency for a building window.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param transparency 0 equals opaque, 1 equals invisible
|
||||
*/
|
||||
void SetWallTransparency(unsigned int contextId, float transparency) override;
|
||||
|
||||
/**
|
||||
* All views with "LockViewRotationToMapRotation" enabled will rotate their camera
|
||||
* to have a camera angle looking towards north, rotated by input angle.
|
||||
* @returnRotation angle in degrees from north CCW
|
||||
*/
|
||||
float GetMapRotation() const override;
|
||||
|
||||
/**
|
||||
* All views with "LockViewRotationToMapRotation" enabled will rotate their camera
|
||||
* to have a camera angle looking towards north, rotated by input angle.
|
||||
* @param angle Rotation angle in degrees from north CCW
|
||||
*/
|
||||
void SetMapRotation(float angle) override;
|
||||
|
||||
/**
|
||||
* Open 3d view of whole terrain - for debugging purposes only!
|
||||
*/
|
||||
void OpenOverview() override;
|
||||
|
||||
|
||||
/**
|
||||
* add buildings to scene and recalculate navigation meshes
|
||||
* @param path Load map from this path. example: "Projections/data.xml"
|
||||
* @param loadAllAvailableBuildings If true, the path variable (=XML file with building configuration) will be ignored)
|
||||
*/
|
||||
bool LoadBuildingPositionMap(const std::string &path, bool loadAllAvailableBuildings) override;
|
||||
|
||||
|
||||
void LoadAllBuildings();
|
||||
|
||||
/**
|
||||
* Create new player at (0,0,0). Player is initially invisible!
|
||||
* @param id a unique string that can later be used to reference the player
|
||||
* @param iconpath system file path to player icon. Can be relative to ProjectAssets folder root.
|
||||
* @param color Initial color of the player
|
||||
*/
|
||||
void CreatePlayer(const std::string &id, const std::string &iconpath, const Color &color) override;
|
||||
|
||||
/**
|
||||
* Delete player with given id
|
||||
* @param seconds Delete player n seconds from now
|
||||
*/
|
||||
void DeletePlayer(const std::string &id, float seconds = 0) override;
|
||||
|
||||
/**
|
||||
* This color is added to the player texture color.
|
||||
*/
|
||||
void SetPlayerColor(const std::string &id, const Color &color) override;
|
||||
|
||||
/**
|
||||
* Set icon path for existing player
|
||||
* @param path system file path to player icon. Can be relative to ProjectAssets folder root.
|
||||
* If path is to current icon path then icon is reloaded from file.
|
||||
*/
|
||||
void SetPlayerIcon(const std::string &id, const std::string &path) override;
|
||||
|
||||
|
||||
void reloadPlayerIcons() override;
|
||||
|
||||
void UpdatePlayerPartyColors(const std::map<std::string, VCtrl::Color>& mapPlayerColors) override;
|
||||
|
||||
/**
|
||||
* Return number of soldier instances
|
||||
*/
|
||||
size_t GetNumPlayers() const override;
|
||||
|
||||
/**
|
||||
* Fill vector with ids of all existing players
|
||||
*/
|
||||
void GetPlayerIds(std::vector<std::string> &toFill) override;
|
||||
|
||||
/**
|
||||
* Hide or unhide player with given id
|
||||
* @param show true to show, false to hide
|
||||
* @param when simulation time when show or hide should be executed
|
||||
*/
|
||||
void SetPlayerShown(const std::string &id, bool show, double when = -1) override;
|
||||
|
||||
/**
|
||||
* Return number of building instances
|
||||
*/
|
||||
size_t GetNumBuildings() const override;
|
||||
|
||||
/**
|
||||
* Fill vector with ids of all existing buildings
|
||||
*/
|
||||
void GetBuildingIds(std::vector<std::string> &toFill) const override;
|
||||
|
||||
/**
|
||||
* Add or remove visible bounding box around entity
|
||||
* @param id unique id of entity
|
||||
* @param show set true to show box, false to make invisible
|
||||
* @param duration If non-negative, remove box after duration seconds
|
||||
*/
|
||||
void SetShowSelectionBox(const std::string &id,
|
||||
bool show,
|
||||
float duration = -1) override;
|
||||
|
||||
/**
|
||||
* Add a line from start to end
|
||||
* Line is displayed by an array of sprites, placed
|
||||
* in equal intervals.
|
||||
* Sprites move toward target with given speed in m/s
|
||||
* Line is deleted after duration seconds.
|
||||
* If duration is 0 then line is never deleted
|
||||
*/
|
||||
void Shoot(const int32_t id,
|
||||
const std::string &shooter,
|
||||
const std::string &target,
|
||||
const Vec3d &shooterPos,
|
||||
const Vec3d &targetPos,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst,
|
||||
int lineType,
|
||||
double when) override;
|
||||
void Shoot(const int32_t id,
|
||||
const std::string &shooter,
|
||||
const std::string &targetBuildingId,
|
||||
const std::string &targetRoomId,
|
||||
const Vec3d &shooterPos, int lineType,
|
||||
double when) override;
|
||||
|
||||
void removeShoot(const int32_t id) override;
|
||||
|
||||
/**
|
||||
* Directly move player to target position, do not use pathfinding. Cancels current path following activity.
|
||||
* @param id Id of player
|
||||
* @param when Simulation time when teleport should happen
|
||||
* @param target position to teleport to
|
||||
* @param bldgname name of building containing position, empty string to ignore
|
||||
* @param roomname name of room containing position, empty string to ignore
|
||||
*/
|
||||
void Teleport(const std::string &id,
|
||||
double when,
|
||||
const Vec3d &target,
|
||||
const std::string &bldgname,
|
||||
int roomNumber,
|
||||
const std::string &roomname,
|
||||
ZValue zval) override;
|
||||
|
||||
/**
|
||||
* Get names of all rooms in building
|
||||
* @param id Id of building player
|
||||
* @param names will be filled with room names
|
||||
*/
|
||||
void GetRoomNames(const std::string &id, std::vector<std::string> &names) override;
|
||||
|
||||
/**
|
||||
* Sets destruction value for room of a building.
|
||||
* @param id Id of building player
|
||||
* @param roomnumber number of room to set (ex: "2001")
|
||||
* @param value destruction value. 0: not destroyed, 1: fully destroyed
|
||||
* @return true if room was found
|
||||
*/
|
||||
bool SetRoomDestructionValue(const std::string &id,
|
||||
const std::string &roomname,
|
||||
float value) override;
|
||||
|
||||
/**
|
||||
* Sets destruction value for all rooms of a building.
|
||||
* @param id Id of building player
|
||||
* @param value destruction value. 0: not destroyed, 1: fully destroyed
|
||||
* @return true if room was found
|
||||
*/
|
||||
bool SetBuildingDestructionValue(const std::string &id, float value) override;
|
||||
|
||||
/**
|
||||
* Get names of all cameras, loudspeakers and other devices in building
|
||||
* @param buildingid Id of building player
|
||||
* @param names will be filled with device names
|
||||
*/
|
||||
void GetDeviceNames(const std::string &buildingId, std::vector<std::string> &names) override;
|
||||
|
||||
/**
|
||||
* Show an icon at center position of device node
|
||||
* @param id unique id for entity that can be used to hide it at a later point
|
||||
* @param buildingid id of building containing the device
|
||||
* @param devicename name of device node to show icon at
|
||||
* @param iconpath absolute path to icon to show at device position
|
||||
* @return true if device was found in building
|
||||
*/
|
||||
bool ShowDeviceIcon(const std::string &id, const std::string &buildingid,
|
||||
const std::string &devicename, const std::string &iconpath) override;
|
||||
|
||||
/**
|
||||
* Show an icon at center position of device node
|
||||
* @param id unique id for entity that can be used to hide it at a later point
|
||||
* @param buildingid id of building containing the device
|
||||
* @param position Position of camera relative to building
|
||||
* @param iconpath absolute path to icon to show at device position
|
||||
* @return true if device was found in building
|
||||
*/
|
||||
bool ShowDeviceIcon(const std::string &id, const std::string &buildingid,
|
||||
const Vec3d &position, const std::string &iconpath) override;
|
||||
|
||||
void ChangeLineMode(unsigned int contextId, bool line) override;
|
||||
void ChangeNameMode(unsigned int contextId, bool name) override;
|
||||
|
||||
bool SetDisplayName(const std::string& buildingid, const std::string& roomname, const std::string& strDisplayName) override;
|
||||
void ShowDisplayNames(const std::string& buildingid, bool show) override;
|
||||
void SetShowDisplayNamesSelectionBox(const std::string& buildingid, const std::string& id, bool show, float duration = -1) override;
|
||||
void setHitLineDuration(uint32_t durationSec) override;
|
||||
void setMountingPointAsset(const MountingPointDescription &asset) override;
|
||||
std::vector<BuildingState> getBuildingState() const override;
|
||||
|
||||
/**
|
||||
* Hide device icon created with ShowDevice
|
||||
* @param id Id used in call to ShowDevice
|
||||
* @return true if device entity was found and successfully removed
|
||||
*/
|
||||
bool HideDeviceIcon(const std::string &id) override;
|
||||
|
||||
/**
|
||||
* Get time scale. Scale 1 is normal, scale 2 is double normal speed
|
||||
*/
|
||||
float GetTimeScale() const override;
|
||||
|
||||
/**
|
||||
* Scale time. Scale 1 is normal, scale 2 is double normal speed
|
||||
*/
|
||||
void SetTimeScale(float scale) override;
|
||||
|
||||
/**
|
||||
* Set current simulation time in seconds
|
||||
*/
|
||||
void SetSimulationTime(double t) override;
|
||||
|
||||
/**
|
||||
* Get current simulation time in seconds
|
||||
*/
|
||||
double GetSimulationTime() const override;
|
||||
|
||||
/**
|
||||
* Pause simulation time and all events
|
||||
*/
|
||||
void SetPaused(bool) override;
|
||||
|
||||
/**
|
||||
* Is simulation currently paused?
|
||||
*/
|
||||
bool GetPaused() const override;
|
||||
|
||||
/**
|
||||
* Advance simulation until given simulation time is reached
|
||||
*/
|
||||
void FastForwardSimulationTo(double t) override;
|
||||
|
||||
/**
|
||||
* Remove all queued commands for soldiers
|
||||
*/
|
||||
void DeleteQueuedCommands() override;
|
||||
|
||||
/**
|
||||
* Switch on or off non realtime mode.
|
||||
* Non realtime mode is used for recording videos at faster than real time speed.
|
||||
* Frames are rendered and compressed as fast as possible, simulation time
|
||||
* does not correspond to real time.
|
||||
*/
|
||||
void SetNonRealtimeMode(bool on) override;
|
||||
|
||||
/**
|
||||
* Is non-realtime mode on or off?
|
||||
*/
|
||||
bool GetNonRealtimeMode() const override;
|
||||
|
||||
/**
|
||||
* Start recording an mpeg video of the view.
|
||||
* @param contextid context id of the view to record.
|
||||
* @param path Record to this file. Extension should be .mpg
|
||||
* @param w width of recorded video file (input is rescaled)
|
||||
* @param h height of recorded video file (input is rescaled)
|
||||
* @param framerate frames per second to record. Reasonable value: 15 - 30
|
||||
* @param quality Compression quality in percent.
|
||||
*/
|
||||
bool StartVideoRecording(unsigned int contextid, const std::string &path,
|
||||
int w, int h, int framerate, int quality) override;
|
||||
bool StartVideoRecording(const std::string &buildingId, const std::string &path,
|
||||
int w, int h, int framerate, int quality) override;
|
||||
|
||||
/**
|
||||
* Stop recording
|
||||
* @param contextid context id of the view to record.
|
||||
*/
|
||||
bool StopVideoRecording(unsigned int contextid) override;
|
||||
bool StopVideoRecording(const std::string &buildingId) override;
|
||||
|
||||
void setTransparency(double percent) override;
|
||||
void setViewMode(ViewMode m) override;
|
||||
void setDisplayMode(PlayerDisplayMode m) override;
|
||||
|
||||
int GetFrameRate() const { return mFrameRate; }
|
||||
void OnShowMsgBox(const std::string &strText);
|
||||
|
||||
bool allViewWindowsExposed() const
|
||||
{
|
||||
for (auto *vw : m_openedViewWidgets.getViewWidgets())
|
||||
{
|
||||
if (!vw->isOpenGlWindowExposed())
|
||||
return false;
|
||||
}
|
||||
return !m_openedViewWidgets.getViewWidgets().empty();
|
||||
}
|
||||
|
||||
private:
|
||||
bool open(const std::string& strFeatureID, bool exactPos);
|
||||
bool open(const std::vector<std::string> &vecFeatureIDs, bool exactPos);
|
||||
bool openAll(bool exactPos);
|
||||
|
||||
void onEXCOpen(const QString& strIDs, bool exactPos);
|
||||
void onEXCClose(const QString& strIDs);
|
||||
void convertAssetsToPngFiles();
|
||||
|
||||
void OnTransformSend(const dtEntity::Message &m);
|
||||
void OnMapLoaded(const dtEntity::Message &m);
|
||||
void OnMapUnloaded(const dtEntity::Message &m);
|
||||
void OnNavMeshGroupChanged(const dtEntity::Message &m);
|
||||
void OnPlayerPicked(const dtEntity::Message &m);
|
||||
void OnHideSelection(const dtEntity::Message &m);
|
||||
//void OnRemoveShoot(const dtEntity::Message &m);
|
||||
void OnShoot(const dtEntity::Message &m);
|
||||
void OnShowHidePlayer(const dtEntity::Message &m);
|
||||
void OnDisplayNameClicked(const dtEntity::Message& m);
|
||||
|
||||
bool SpawnBuilding(const BuildingData &b, bool useStaticMeshesFolder = true);
|
||||
void LoadBuilding(BuildingData& bd, bool useStaticMeshesFolder);
|
||||
void deleteAllBuildings();
|
||||
|
||||
bool getBuildingString(const std::string &strFeatureID, std::string *strBuildingNameID);
|
||||
|
||||
bool OpenView(unsigned int contextId);
|
||||
bool CreateView(dtEntity::EntityId bid, const std::string &windowtitle, const Color &col, ViewMode viewmode,
|
||||
int screennum, bool fullscreen, int x, int y, int w, int h,
|
||||
unsigned int &contextid, bool exactPos);
|
||||
|
||||
QPointer<CtrlMainWindow> m_pMainWindow;
|
||||
|
||||
dtEntity::EntityManager *mEntityManager;
|
||||
ViewerCallback *mViewerCallback;
|
||||
LogHandler* mLogHandler = nullptr;
|
||||
dtEntity::MapSystem *mMapSystem;
|
||||
PlayerSystem *mPlayerSystem;
|
||||
BuildingManager *mBuildingManager;
|
||||
|
||||
float mTimeScale;
|
||||
double mSimTime;
|
||||
bool mPaused;
|
||||
bool mNonRealtimeMode;
|
||||
int mFrameRate; // only for non realtime mode
|
||||
std::map<unsigned int, ViewWidget *> mViewWidgets; // contextIDs to ViewWidgets
|
||||
|
||||
|
||||
ViewWidget *GetViewWidget(unsigned int contextid);
|
||||
void storeWidget(ViewWidget *pWidget, const std::string &strBuildingNameID, unsigned int contextid, VCtrl::ViewMode vmode, VCtrl::PlayerDisplayMode displayMode);
|
||||
|
||||
|
||||
const std::size_t m_maxParallelViewWidgets = 8;
|
||||
// Global setting for all ViewWidgets
|
||||
unsigned int m_hitlineDuration_s = 10;
|
||||
double m_desiredTransparencyValue = 0.75;
|
||||
bool m_showHitLines = true;
|
||||
ViewWidget *CreateMainWindowView(dtEntity::EntityId bid, const std::string &featureId, unsigned int &contextid, bool exactPos);
|
||||
|
||||
|
||||
std::unordered_map<std::string, BuildingData> m_loadedBuildings; // Feature_IDs
|
||||
|
||||
ViewWidgetContainer m_openedViewWidgets;
|
||||
bool m_isInFullscreenMode = false;
|
||||
|
||||
// Global Settings valid for all newly opened widgets
|
||||
ViewMode m_desiredViewMode = ViewMode::ORTHOGRAPHIC;
|
||||
VCtrl::PlayerDisplayMode m_desiredPlayerDisplayMode = VCtrl::PlayerDisplayMode::Icons;
|
||||
|
||||
void CloseView(ViewWidget *pWidget);
|
||||
|
||||
void onExcRestoreViewState(const std::string &strFeatureID);
|
||||
void restoreViewWidgetStates(const std::vector<BuildingViewer::ViewWidgetState> &vecStates);
|
||||
void restoreViewWidgetStateDeferred(ViewWidget *pViewWidget);
|
||||
std::unordered_map<std::string, BuildingViewer::ViewWidgetState> m_deferredViewStates;
|
||||
|
||||
QJsonValue getViewState() const override;
|
||||
void setViewState(const QJsonValue &val) override;
|
||||
void highlightView(const std::string &buildingId) override;
|
||||
void setBuildingDisplayName(const std::string &buildingId, const std::string &displayName) override;
|
||||
//NGL::INGLLogger &m_logger;
|
||||
|
||||
private slots:
|
||||
void onViewWidget_MaximizeRequest(ViewWidget *pWidget);
|
||||
void onViewWidget_MinimizeRequest(ViewWidget *pWidget);
|
||||
void onViewWidget_CloseRequest(ViewWidget *pWidget);
|
||||
void onViewWidget_FocusRequest(ViewWidget *pWidget);
|
||||
void onViewWidget_Zoom(ViewWidget *pWidget, bool zoomIn);
|
||||
};
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
#include "viewermainwindow.h"
|
||||
#include "viewwidget.h"
|
||||
#include "viewerinterfaceimpl.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TransparencyDialog::TransparencyDialog(QWidget *parent)
|
||||
: QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
|
||||
{
|
||||
setWindowTitle(tr("BgViewer - Set Global Transparency"));
|
||||
|
||||
auto plabel = new QLabel(tr("Set transparency value:"));
|
||||
m_pSlider = new QSlider(Qt::Horizontal);
|
||||
m_pSlider->setMinimum(0);
|
||||
m_pSlider->setMaximum(100);
|
||||
m_pSlider->setValue(50);
|
||||
m_pSlider->setMinimumWidth(200);
|
||||
|
||||
auto pButton = new QPushButton(tr("Apply"));
|
||||
connect(pButton, &QPushButton::clicked, this, &VCtrl::TransparencyDialog::accept);
|
||||
|
||||
|
||||
auto pLayout = new QHBoxLayout(this);
|
||||
pLayout->addWidget(plabel);
|
||||
pLayout->addWidget(m_pSlider);
|
||||
pLayout->addWidget(pButton);
|
||||
pLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CtrlMainWindow::CtrlMainWindow(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
connect(&m_highlighterTimer, &QTimer::timeout,
|
||||
this, &CtrlMainWindow::onHighlighterTimerTimeout);
|
||||
setWindowTitle(tr("BgViewer"));
|
||||
// Remove minimize/maximize and close button
|
||||
setWindowFlags(Qt::Window | Qt::CustomizeWindowHint);
|
||||
|
||||
new QGridLayout(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::updateHighlightThreads(ViewWidget *pWidget)
|
||||
{
|
||||
m_highlighterCounter[pWidget] = 6;
|
||||
if (!m_highlighterTimer.isActive())
|
||||
m_highlighterTimer.start(500);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::onHighlighterTimerTimeout()
|
||||
{
|
||||
auto it = m_highlighterCounter.begin();
|
||||
while (it != m_highlighterCounter.end())
|
||||
{
|
||||
ViewWidget *ww = it.key();
|
||||
ww->highlightBorder(it.value() % 2 == 0);
|
||||
it.value() = it.value() - 1;
|
||||
if (it.value() <= 0)
|
||||
it = m_highlighterCounter.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
if (m_highlighterCounter.isEmpty())
|
||||
m_highlighterTimer.stop();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::openView(ViewWidget *pViewWidget)
|
||||
{
|
||||
openViews({pViewWidget});
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::openViews(const std::vector<ViewWidget *> &vecMainWindowSubWidgets)
|
||||
{
|
||||
constexpr int maxViewsPerCol = 4;
|
||||
|
||||
// Append where we stopped last time
|
||||
QGridLayout *gridLayout = static_cast<QGridLayout *>(layout());
|
||||
int row = gridLayout->count() / maxViewsPerCol, col = gridLayout->count() % maxViewsPerCol;
|
||||
|
||||
// Add all requested ViewWidgets which are actually new
|
||||
for (auto &pWidget : vecMainWindowSubWidgets)
|
||||
{
|
||||
auto itm = gridLayout->itemAtPosition(row, col);
|
||||
if (itm && itm->widget() == pWidget)
|
||||
continue;
|
||||
gridLayout->addWidget(pWidget, row, col);
|
||||
pWidget->show();
|
||||
|
||||
if (++col >= maxViewsPerCol)
|
||||
{
|
||||
col = 0;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CtrlMainWindow::closeView(ViewWidget *pViewWidget)
|
||||
{
|
||||
if (!pViewWidget)
|
||||
return;
|
||||
QGridLayout *gridLayout = dynamic_cast<QGridLayout *>(layout());
|
||||
std::vector<ViewWidget*> currentViews;
|
||||
currentViews.reserve(gridLayout->count());
|
||||
for (int idx = 0; idx < gridLayout->count(); idx++)
|
||||
{
|
||||
QLayoutItem *item = gridLayout->itemAt(idx);
|
||||
ViewWidget *vw = static_cast<ViewWidget*>(item->widget());
|
||||
if (vw != pViewWidget)
|
||||
currentViews.push_back(vw);
|
||||
}
|
||||
m_highlighterCounter.remove(pViewWidget);
|
||||
pViewWidget->close();
|
||||
|
||||
delete gridLayout;
|
||||
setLayout(new QGridLayout);
|
||||
openViews(currentViews);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::clearGridLayout()
|
||||
{
|
||||
QGridLayout *gridLayout = dynamic_cast<QGridLayout *>(layout());
|
||||
for (int idx = 0; idx < gridLayout->count(); idx++)
|
||||
{
|
||||
QLayoutItem *item = gridLayout->itemAt(idx);
|
||||
item->widget()->hide();
|
||||
}
|
||||
m_highlighterCounter.clear();
|
||||
|
||||
delete gridLayout;
|
||||
setLayout(new QGridLayout);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef VCTRL_CTRLMAINWINDOW_H
|
||||
#define VCTRL_CTRLMAINWINDOW_H
|
||||
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSlider>
|
||||
#include <QTimer>
|
||||
#include <QHash>
|
||||
|
||||
#include "viewerinterface.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class TransparencyDialog final : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TransparencyDialog(QWidget *parent = nullptr);
|
||||
double getTransparencyValue() const
|
||||
{
|
||||
return m_pSlider->value() / 100.0;
|
||||
}
|
||||
private:
|
||||
QSlider *m_pSlider;
|
||||
};
|
||||
|
||||
|
||||
class ViewWidget;
|
||||
class CtrlImpl;
|
||||
|
||||
|
||||
class CtrlMainWindow final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CtrlMainWindow(QWidget *parent);
|
||||
|
||||
void openView(ViewWidget *pViewWidget);
|
||||
void openViews(const std::vector<ViewWidget *> &vecMainWindowSubWidgets);
|
||||
void closeView(ViewWidget *pViewWidget);
|
||||
void updateHighlightThreads(ViewWidget *pWidget);
|
||||
void clearGridLayout();
|
||||
|
||||
private:
|
||||
void onHighlighterTimerTimeout();
|
||||
private:
|
||||
QTimer m_highlighterTimer;
|
||||
QHash<ViewWidget *, int> m_highlighterCounter;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // VCTRL_CTRLMAINWINDOW_H
|
||||
@@ -0,0 +1,390 @@
|
||||
#include "viewwidget.h"
|
||||
#include "viewwidgetstate.h"
|
||||
#include <QApplication>
|
||||
#include <QVBoxLayout>
|
||||
#include <QEvent>
|
||||
#include <QGLWidget>
|
||||
#include <QWindow>
|
||||
#include <dtEntity/log.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
ViewWidgetState::ViewWidgetState(VCtrl::ViewWidget* pView)
|
||||
: m_featureID(pView->featureID())
|
||||
, m_usedTransparencyValue(pView->transparency())
|
||||
, m_windowWidth(pView->accessView()->width())
|
||||
, m_windowHeight(pView->accessView()->height())
|
||||
, m_lockActive(pView->lockedRotation())
|
||||
, m_dotsActive(pView->dotModeActive())
|
||||
, m_isMaximized(pView->isMaximized())
|
||||
, m_namesActive(pView->nameModeActive())
|
||||
, m_usesOrtho(pView->viewMode() == VCtrl::ViewMode::ORTHOGRAPHIC)
|
||||
, m_usesExactPos(pView->exactPos())
|
||||
{}
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
const QColor ViewWidget::ColorBorder = QColor(48, 136, 209);
|
||||
const QColor ViewWidget::ColorSelected = QColor(90, 200, 255);
|
||||
const QColor ViewWidget::ColorHighlighted = Qt::green;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ViewWidget::ViewWidget(unsigned int contextid, dtEntity::EntityId bid, const std::string &strFeatureID, bool usesExactPos, QWidget *parent)
|
||||
: QFrame(parent),
|
||||
m_locked(false),
|
||||
m_useDotMode(false),
|
||||
m_entityID(bid),
|
||||
m_featureID(strFeatureID),
|
||||
mContextId(contextid),
|
||||
m_usesExactPos(usesExactPos),
|
||||
mViewerInterface(nullptr),
|
||||
mClosedByAPI(false),
|
||||
m_pView(nullptr)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
m_toolButton_maximize->setIcon(QIcon(QStringLiteral("icon:bgv_view_maximize.svg")));
|
||||
m_toolButton_close->setIcon(QIcon(QStringLiteral("icon:bgv_view_close.svg")));
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_iso.svg")));
|
||||
m_toolButton_dots->setIcon(QIcon(QStringLiteral("icon:bgv_view_symbols.svg")));
|
||||
m_toolButton_lockRotation->setIcon(QIcon(QStringLiteral("icon:bgv_view_unlock.svg")));
|
||||
m_toolButton_rooms->setIcon(QIcon(QStringLiteral("icon:bgv_room_edit.svg")));
|
||||
|
||||
m_toolButton_viewmode->setChecked(m_viewmode != ViewMode::ISOMETRIC);
|
||||
m_toolButton_dots->setChecked(m_useDotMode);
|
||||
m_toolButton_lockRotation->setChecked(m_locked);
|
||||
|
||||
m_toolButton_ZoomOut->setIcon(QIcon(QStringLiteral("icon:bgv_zoom_out.svg")));
|
||||
m_toolButton_ZoomIn->setIcon(QIcon(QStringLiteral("icon:bgv_zoom_in.svg")));
|
||||
|
||||
QIcon iconT(QStringLiteral("icon:bgv_transparency.svg"));
|
||||
QPixmap image(iconT.pixmap(30,30));
|
||||
m_label_transparency->setPixmap(image);
|
||||
|
||||
connect(m_toolButton_viewmode, &QToolButton::clicked, this, &ViewWidget::viewModeChanged);
|
||||
connect(_transparency, &QSlider::valueChanged, this, &ViewWidget::transparencyChanged);
|
||||
connect(m_toolButton_lockRotation, &QToolButton::clicked, this, &ViewWidget::lockRotationToggled);
|
||||
connect(m_toolButton_dots, &QToolButton::clicked, this, &ViewWidget::dotModeToggled);
|
||||
connect(m_toolButton_rooms, &QToolButton::clicked, this, &ViewWidget::nameModeToggled);
|
||||
connect(m_toolButton_more, &QToolButton::clicked, this, &ViewWidget::slotShowMore);
|
||||
connect(m_toolButton_maximize, &QToolButton::clicked, this, &ViewWidget::OnButtonMaximize);
|
||||
connect(m_toolButton_close, &QToolButton::clicked, this, &ViewWidget::OnButtonClose);
|
||||
|
||||
connect(m_toolButton_ZoomOut, &QToolButton::clicked, this, [this](){
|
||||
emit signal_Zoom(this, false);
|
||||
});
|
||||
connect(m_toolButton_ZoomIn, &QToolButton::clicked, this, [this](){
|
||||
emit signal_Zoom(this, true);
|
||||
});
|
||||
|
||||
m_toolButton_maximize->setEnabled(true);
|
||||
|
||||
setSelected(false);
|
||||
setMouseTracking(true); // Otherwise ViewWidget::mouseMoveEvent would not receive any events
|
||||
|
||||
slotShowMore(false);
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::highlightBorder(bool highlight)
|
||||
{
|
||||
if (highlight)
|
||||
drawBorder(ColorHighlighted);
|
||||
else
|
||||
drawBorder(isSelected() ? ColorSelected : ColorBorder);
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::dotModeToggled()
|
||||
{
|
||||
if (!mViewerInterface) return;
|
||||
|
||||
m_useDotMode ^= true;
|
||||
mViewerInterface->SetPlayerDisplayMode(mContextId, m_useDotMode ? PlayerDisplayMode::Dots : PlayerDisplayMode::Icons);
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::drawBorder(const QColor &col)
|
||||
{
|
||||
setStyleSheet(QStringLiteral("#ViewWidget { border: 2px solid %1; }").arg(col.name()));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::closeByAPI()
|
||||
{
|
||||
mClosedByAPI = true;
|
||||
this->close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setText(const QString &strText)
|
||||
{
|
||||
m_label_description->setText(strText);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::closeEvent(QCloseEvent *e)
|
||||
{
|
||||
if (mViewerInterface && !mClosedByAPI)
|
||||
mViewerInterface->CloseView(mContextId);
|
||||
QFrame::closeEvent(e);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setDisplayedViewMode(ViewMode vm)
|
||||
{
|
||||
if (vm == ViewMode::ORTHOGRAPHIC)
|
||||
{
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_iso.svg")));
|
||||
}
|
||||
else if (vm == ViewMode::ISOMETRIC)
|
||||
{
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_ortho.svg")));
|
||||
}
|
||||
|
||||
m_viewmode = vm;
|
||||
m_toolButton_viewmode->setChecked(m_viewmode != ViewMode::ISOMETRIC);
|
||||
m_toolButton_dots->setChecked(m_useDotMode);
|
||||
m_toolButton_lockRotation->setChecked(m_locked);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::viewModeChanged()
|
||||
{
|
||||
if (!mViewerInterface) return;
|
||||
|
||||
if (m_viewmode == ViewMode::ORTHOGRAPHIC)
|
||||
{
|
||||
m_viewmode = ViewMode::ISOMETRIC;
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_iso.svg")));
|
||||
mViewerInterface->ChangeViewMode(mContextId, m_viewmode);
|
||||
}
|
||||
else if (m_viewmode == ViewMode::ISOMETRIC)
|
||||
{
|
||||
m_viewmode = ViewMode::ORTHOGRAPHIC;
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_ortho.svg")));
|
||||
mViewerInterface->ChangeViewMode(mContextId, m_viewmode);
|
||||
}
|
||||
m_toolButton_viewmode->setChecked(m_viewmode != ViewMode::ISOMETRIC);
|
||||
}
|
||||
|
||||
bool ViewWidget::isOpenGlWindowExposed() const
|
||||
{
|
||||
QGLWidget *gl = qobject_cast<QGLWidget*>(m_pView);
|
||||
if (!gl || !gl->windowHandle())
|
||||
return false;
|
||||
return gl->windowHandle()->isExposed();
|
||||
}
|
||||
|
||||
void ViewWidget::setMaximized(bool maximized)
|
||||
{
|
||||
m_toolButton_maximize->setIcon(maximized ?
|
||||
QIcon(QStringLiteral("icon:bgv_view_minimize.svg")) :
|
||||
QIcon(QStringLiteral("icon:bgv_view_maximize.svg")));
|
||||
m_isMaximized = maximized;
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::setSelected(bool selected)
|
||||
{
|
||||
m_isSelected = selected;
|
||||
drawBorder(m_isSelected ? ColorSelected : ColorBorder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
double ViewWidget::transparency() const {
|
||||
return static_cast<double>(_transparency->value()) / 100.0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setTransparency(float value)
|
||||
{
|
||||
_transparency->setValue(qRound(value * 100));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::transparencyChanged(int v)
|
||||
{
|
||||
if (!mViewerInterface) return;
|
||||
mViewerInterface->SetWallTransparency(mContextId, float(v) / 100.0f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ViewWidget::lockedRotation() const
|
||||
{
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
|
||||
bool ViewWidget::dotModeActive() const
|
||||
{
|
||||
return m_useDotMode;
|
||||
}
|
||||
|
||||
|
||||
bool ViewWidget::nameModeActive() const
|
||||
{
|
||||
return m_toolButton_rooms->isChecked();
|
||||
}
|
||||
|
||||
|
||||
ViewMode ViewWidget::viewMode() const {
|
||||
return m_viewmode;
|
||||
}
|
||||
|
||||
bool ViewWidget::exactPos() const
|
||||
{
|
||||
return m_usesExactPos;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setLockRotationCheckbox(bool v)
|
||||
{
|
||||
m_locked = v;
|
||||
m_toolButton_lockRotation->setIcon(m_locked ?
|
||||
QIcon(QStringLiteral("icon:bgv_view_lock.svg")) :
|
||||
QIcon(QStringLiteral("icon:bgv_view_unlock.svg")));
|
||||
m_toolButton_lockRotation->setChecked(m_locked);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setDotModeCheckbox(bool v)
|
||||
{
|
||||
m_useDotMode = v;
|
||||
m_toolButton_dots->setIcon(m_useDotMode ?
|
||||
QIcon(QStringLiteral("icon:bgv_view_dots.svg")) :
|
||||
QIcon(QStringLiteral("icon:bgv_view_symbols.svg")));
|
||||
m_toolButton_dots->setChecked(m_useDotMode);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setNameModeCheckbox(bool v)
|
||||
{
|
||||
m_toolButton_rooms->setChecked(v);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::lockRotationToggled()
|
||||
{
|
||||
if (!mViewerInterface) return;
|
||||
|
||||
m_locked ^= true;
|
||||
mViewerInterface->LockViewRotationToMapRotation(mContextId, m_locked);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::slotShowMore(bool v)
|
||||
{
|
||||
widget->setVisible(v);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::nameModeToggled(bool v)
|
||||
{
|
||||
if(!mViewerInterface) return;
|
||||
mViewerInterface->ChangeNameMode(mContextId, v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::OnButtonMaximize(bool)
|
||||
{
|
||||
if (m_isMaximized)
|
||||
{
|
||||
emit signal_MinimizeRequest(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit signal_MaximizeRequest(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::OnButtonClose(bool)
|
||||
{
|
||||
emit signal_CloseRequest(this);
|
||||
}
|
||||
|
||||
|
||||
QWidget* ViewWidget::accessView()
|
||||
{
|
||||
return m_pView;
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
emit signal_FocusRequest(this);
|
||||
QFrame::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
|
||||
bool ViewWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseMove)
|
||||
emit signal_FocusRequest(this);
|
||||
if (obj == m_pView && event->type() == QEvent::Show)
|
||||
emit signal_ViewIsShown(this);
|
||||
|
||||
return QFrame::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void ViewWidget::showEvent(QShowEvent *event)
|
||||
{
|
||||
QWidget::showEvent(event);
|
||||
updateTlwTransientParent();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setView(QWidget *view)
|
||||
{
|
||||
if (m_pView)
|
||||
{
|
||||
m_pView->removeEventFilter(this);
|
||||
layout()->removeWidget(m_pView);
|
||||
}
|
||||
m_pView = view;
|
||||
m_pView->installEventFilter(this);
|
||||
QVBoxLayout *vLay = qobject_cast<QVBoxLayout*>(layout());
|
||||
if (!vLay)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
vLay->addWidget(m_pView);
|
||||
updateTlwTransientParent();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::updateTlwTransientParent()
|
||||
{
|
||||
// this is a workaround for Qt < 5.12 which does not set the correct blocking state for
|
||||
// the toplevel widget where this ViewWidget lives in when there is a model dialog (which
|
||||
// means all other TLWs are blocked) and a native window (like e.g. QGLWidget) is added as
|
||||
// a child therefore we have to trigger and update of the blocking state of the complete
|
||||
// hierarchy to make sure we don't get out of sync. It's fixed in at least 5.12, but could
|
||||
// not find out the commit / bug report for it. If you want to debug,
|
||||
// QGuiApplicationPrivate::updateBlockedStatus() is a good starting point for this.
|
||||
if (QApplication::activeModalWidget())
|
||||
{
|
||||
QWidget *tlw = window();
|
||||
if (tlw && tlw->windowHandle())
|
||||
tlw->windowHandle()->setTransientParent(tlw->windowHandle()->transientParent());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QColor>
|
||||
#include <QWidget>
|
||||
#include <QDockWidget>
|
||||
#include "ui_viewwidget.h"
|
||||
#include "viewerinterface.h"
|
||||
|
||||
#include <string>
|
||||
#include "dtEntity/entityid.h"
|
||||
|
||||
|
||||
namespace osgViewer {
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class ViewWidget
|
||||
: public QFrame, // QWidget, (Needs to be QFrame to set border properties such as color)
|
||||
public Ui::ViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ViewWidget(unsigned int contextid,
|
||||
dtEntity::EntityId bid = 0,
|
||||
const std::string &strFeatureID = std::string(),
|
||||
bool usesExactPos = false,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
static const QColor ColorBorder;
|
||||
static const QColor ColorSelected;
|
||||
static const QColor ColorHighlighted;
|
||||
|
||||
void setView(QWidget *view);
|
||||
QWidget* accessView();
|
||||
void setText(const QString &strText);
|
||||
void closeEvent(QCloseEvent *e) override;
|
||||
|
||||
void setViewerInterface(ViewerInterface *v) { mViewerInterface = v; }
|
||||
|
||||
|
||||
bool isOpenGlWindowExposed() const;
|
||||
|
||||
inline bool isMaximized() const
|
||||
{
|
||||
return m_isMaximized;
|
||||
}
|
||||
|
||||
void setMaximized(bool maximized);
|
||||
void setSelected(bool selected);
|
||||
inline bool isSelected() const
|
||||
{
|
||||
return m_isSelected;
|
||||
}
|
||||
|
||||
inline unsigned int contextID() const
|
||||
{
|
||||
return mContextId;
|
||||
}
|
||||
|
||||
inline dtEntity::EntityId entityID() const
|
||||
{
|
||||
return m_entityID;
|
||||
}
|
||||
|
||||
inline const std::string featureID() const
|
||||
{
|
||||
return m_featureID;
|
||||
}
|
||||
|
||||
inline const std::string description() const
|
||||
{
|
||||
return m_label_description->text().toStdString();
|
||||
}
|
||||
|
||||
|
||||
double transparency() const;
|
||||
bool lockedRotation() const;
|
||||
bool dotModeActive() const;
|
||||
bool nameModeActive() const;
|
||||
ViewMode viewMode() const;
|
||||
bool exactPos() const;
|
||||
|
||||
signals:
|
||||
void signal_Zoom(ViewWidget *pWidget, bool zoomIn);
|
||||
void signal_MaximizeRequest(ViewWidget *pWidget);
|
||||
void signal_MinimizeRequest(ViewWidget *pWidget);
|
||||
void signal_CloseRequest(ViewWidget *pWidget);
|
||||
void signal_FocusRequest(ViewWidget *pWidget);
|
||||
void signal_ViewIsShown(ViewWidget *pWidget);
|
||||
|
||||
|
||||
public slots:
|
||||
void setLockRotationCheckbox(bool);
|
||||
void setDotModeCheckbox(bool);
|
||||
void setNameModeCheckbox(bool);
|
||||
void setDisplayedViewMode(ViewMode);
|
||||
void setTransparency(float value);
|
||||
void closeByAPI();
|
||||
|
||||
void highlightBorder(bool highlight);
|
||||
|
||||
|
||||
protected slots:
|
||||
void viewModeChanged();
|
||||
void transparencyChanged(int);
|
||||
void lockRotationToggled();
|
||||
void dotModeToggled();
|
||||
void nameModeToggled(bool);
|
||||
void slotShowMore(bool);
|
||||
|
||||
void OnButtonMaximize(bool);
|
||||
void OnButtonClose(bool);
|
||||
|
||||
private:
|
||||
void updateTlwTransientParent();
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
bool m_isMaximized = false;
|
||||
bool m_isSelected = false;
|
||||
void drawBorder(const QColor &col);
|
||||
|
||||
bool m_locked, m_useDotMode;
|
||||
ViewMode m_viewmode = ViewMode::ISOMETRIC;
|
||||
|
||||
dtEntity::EntityId m_entityID;
|
||||
std::string m_featureID; // E.g., "House_11" (as specified within the xml files)
|
||||
unsigned int mContextId;
|
||||
|
||||
bool m_usesExactPos;
|
||||
|
||||
ViewerInterface *mViewerInterface;
|
||||
bool mClosedByAPI;
|
||||
QWidget* m_pView;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ViewWidget</class>
|
||||
<widget class="QWidget" name="ViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>333</width>
|
||||
<height>96</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_label_description">
|
||||
<property name="text">
|
||||
<string notr="true">TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_dots">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Dots</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_viewmode">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Ortho</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_toolButton_more">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_maximize">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">O</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_close">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">X</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_lockRotation">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Lock</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_rooms">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Name</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_ZoomOut">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ZOut</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_ZoomIn">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ZoomIn</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_label_transparency">
|
||||
<property name="text">
|
||||
<string notr="true">Transparency: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="_transparency">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
#include "viewwidgetcontainer.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
ViewWidget *ViewWidgetContainer::getViewWidget(unsigned int contextID) const
|
||||
{
|
||||
for (const auto &pView : m_vecViewWidgets)
|
||||
{
|
||||
if (pView->contextID() == contextID)
|
||||
return pView;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void ViewWidgetContainer::add(ViewWidget *pWidget)
|
||||
{
|
||||
m_vecViewWidgets.push_back(pWidget);
|
||||
m_mapFeatureID_To_ViewWidget[pWidget->featureID()] = pWidget;
|
||||
connect(pWidget, &QObject::destroyed, this, &ViewWidgetContainer::onWidgetDestroyed);
|
||||
}
|
||||
|
||||
|
||||
void ViewWidgetContainer::remove(const std::string &featureID)
|
||||
{
|
||||
auto it = m_mapFeatureID_To_ViewWidget.find(featureID);
|
||||
if (it != m_mapFeatureID_To_ViewWidget.end())
|
||||
{
|
||||
ViewWidget *pWidget = it->second;
|
||||
|
||||
auto vecIt = std::find(m_vecViewWidgets.begin(), m_vecViewWidgets.end(), pWidget);
|
||||
if (vecIt != m_vecViewWidgets.end())
|
||||
m_vecViewWidgets.erase(vecIt);
|
||||
|
||||
m_mapFeatureID_To_ViewWidget.erase(it);
|
||||
|
||||
assert(m_vecViewWidgets.size() == m_mapFeatureID_To_ViewWidget.size());
|
||||
}
|
||||
}
|
||||
|
||||
void ViewWidgetContainer::onWidgetDestroyed(QObject *obj)
|
||||
{
|
||||
ViewWidget *pWidget = static_cast<ViewWidget*>(obj);
|
||||
auto vecIt = std::find(m_vecViewWidgets.begin(), m_vecViewWidgets.end(), pWidget);
|
||||
if (vecIt != m_vecViewWidgets.end())
|
||||
m_vecViewWidgets.erase(vecIt);
|
||||
for (auto it = m_mapFeatureID_To_ViewWidget.begin(); it != m_mapFeatureID_To_ViewWidget.end(); ++it)
|
||||
{
|
||||
if (it->second == pWidget)
|
||||
{
|
||||
m_mapFeatureID_To_ViewWidget.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "viewwidget.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class ViewWidgetContainer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
void add(ViewWidget *pWidget);
|
||||
void remove(const std::string &featureID);
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_vecViewWidgets.clear();
|
||||
m_mapFeatureID_To_ViewWidget.clear();
|
||||
}
|
||||
|
||||
|
||||
bool exist(const std::string &featureID) const
|
||||
{
|
||||
return (m_mapFeatureID_To_ViewWidget.find(featureID) != m_mapFeatureID_To_ViewWidget.end());
|
||||
}
|
||||
|
||||
ViewWidget *getViewWidget(const std::string &featureID) const
|
||||
{
|
||||
return exist(featureID) ? m_mapFeatureID_To_ViewWidget.at(featureID) : nullptr;
|
||||
}
|
||||
|
||||
ViewWidget *getViewWidget(unsigned int contextID) const;
|
||||
|
||||
const std::vector<ViewWidget*> &getViewWidgets() const
|
||||
{
|
||||
return m_vecViewWidgets;
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_vecViewWidgets.size();
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void onWidgetDestroyed(QObject *obj);
|
||||
private:
|
||||
// Both containers will always have same size
|
||||
std::vector<ViewWidget *> m_vecViewWidgets; // Keeps track of the ViewWidget ordering (used for the gridlayout)
|
||||
std::map<std::string, ViewWidget *> m_mapFeatureID_To_ViewWidget; // Keeps track about the currently used FeatureIDs (respectively opened ViewWidgets)
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "cameraviewposition.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class ViewWidget;
|
||||
}
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class ViewWidgetState
|
||||
{
|
||||
public:
|
||||
explicit ViewWidgetState(VCtrl::ViewWidget *pView);
|
||||
explicit ViewWidgetState(const QJsonObject &jsonObj)
|
||||
{
|
||||
m_featureID = jsonObj[QStringLiteral("featureID")].toString().toStdString();
|
||||
m_usedTransparencyValue = jsonObj[QStringLiteral("usedTransparencyValue")].toDouble();
|
||||
|
||||
m_posCamera.m_top = jsonObj[QStringLiteral("posCameraTop")].toDouble();
|
||||
m_posCamera.m_left = jsonObj[QStringLiteral("posCameraLeft")].toDouble();
|
||||
m_posCamera.m_bottom = jsonObj[QStringLiteral("posCameraBottom")].toDouble();
|
||||
m_posCamera.m_right = jsonObj[QStringLiteral("posCameraRight")].toDouble();
|
||||
|
||||
m_windowWidth = jsonObj[QStringLiteral("windowWidth")].toInt();
|
||||
m_windowHeight = jsonObj[QStringLiteral("windowHeight")].toInt();
|
||||
|
||||
m_usesExactPos = jsonObj[QStringLiteral("usesExactPos")].toBool();
|
||||
m_lockActive = jsonObj[QStringLiteral("lockActive")].toBool();
|
||||
m_dotsActive = jsonObj[QStringLiteral("dotsActive")].toBool();
|
||||
m_isMaximized = jsonObj[QStringLiteral("isMaximized")].toBool();
|
||||
m_namesActive = jsonObj[QStringLiteral("namesActive")].toBool();
|
||||
m_usesOrtho = jsonObj[QStringLiteral("usesOrtho")].toBool();
|
||||
}
|
||||
|
||||
QJsonObject toJson() const
|
||||
{
|
||||
return {
|
||||
{QStringLiteral("featureID"), QString::fromStdString(m_featureID)},
|
||||
{QStringLiteral("usedTransparencyValue"), m_usedTransparencyValue},
|
||||
{QStringLiteral("posCameraTop"), m_posCamera.m_top},
|
||||
{QStringLiteral("posCameraLeft"), m_posCamera.m_left},
|
||||
{QStringLiteral("posCameraBottom"), m_posCamera.m_bottom},
|
||||
{QStringLiteral("posCameraRight"), m_posCamera.m_right},
|
||||
{QStringLiteral("windowWidth"), m_windowWidth},
|
||||
{QStringLiteral("windowHeight"), m_windowHeight},
|
||||
{QStringLiteral("usesExactPos"), m_usesExactPos},
|
||||
{QStringLiteral("lockActive"), m_lockActive},
|
||||
{QStringLiteral("dotsActive"), m_dotsActive},
|
||||
{QStringLiteral("namesActive"), m_namesActive},
|
||||
{QStringLiteral("isMaximized"), m_isMaximized},
|
||||
{QStringLiteral("usesOrtho"), m_usesOrtho},
|
||||
};
|
||||
}
|
||||
|
||||
std::string m_featureID; // We use featureID (manual string description of a building) since contextID may differ/change depending on implementation
|
||||
double m_usedTransparencyValue = 0.0;
|
||||
BuildingViewer::CameraViewPosition m_posCamera;
|
||||
int m_windowWidth = -1, m_windowHeight = -1;
|
||||
|
||||
bool m_lockActive = false;
|
||||
bool m_dotsActive = false;
|
||||
bool m_isMaximized = false;
|
||||
bool m_namesActive = false;
|
||||
bool m_usesOrtho = false;
|
||||
bool m_usesExactPos = false;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
#include "visitors.h"
|
||||
|
||||
#include <dtEntity/property.h>
|
||||
#include <osg/Material>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/BlendColor>
|
||||
#include <QStringRef>
|
||||
#include <QVector>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindByNameVisitor::apply(osg::Node &node)
|
||||
{
|
||||
const QString grpName(QString::fromStdString(node.getName()));
|
||||
if (grpName.contains(mName, Qt::CaseInsensitive))
|
||||
mNodes.push_back(&node);
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindExactNameVisitor::apply(osg::Node &node)
|
||||
{
|
||||
auto it = mNamesToSearch.find(node.getName());
|
||||
if (it != mNamesToSearch.end())
|
||||
{
|
||||
mNamesToSearch.erase(it);
|
||||
mNodes.push_back(&node);
|
||||
}
|
||||
if (mNamesToSearch.size())
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindRoomNamesVisitor::apply(osg::Node &n)
|
||||
{
|
||||
const std::string &nm = n.getName();
|
||||
|
||||
if (nm.size() > 8 && nm.substr(0, 8) == "SW_room_")
|
||||
{
|
||||
if (n.getNumDescriptions() > 0)
|
||||
{
|
||||
std::string desc = n.getDescription(0);
|
||||
size_t pos = desc.find('@');
|
||||
if (pos != std::string::npos)
|
||||
mNames.push_back(desc.substr(pos + 1, desc.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string roomName = "2" + nm.substr(8, nm.size());
|
||||
mNames.push_back(roomName);
|
||||
std::vector<std::string> descList;
|
||||
descList.push_back(nm + "@" + roomName);
|
||||
n.setDescriptions(descList);
|
||||
}
|
||||
}
|
||||
traverse(n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void ClearVertexColorsVisitor::apply(osg::Geode &geode)
|
||||
{
|
||||
for (unsigned int i = 0; i < geode.getNumDrawables(); ++i)
|
||||
{
|
||||
osg::Geometry *geo = geode.getDrawable(i)->asGeometry();
|
||||
if (geo && geo->getColorArray() != nullptr)
|
||||
{
|
||||
geo->setColorArray(nullptr);
|
||||
geo->setColorBinding(osg::Geometry::BIND_OFF);
|
||||
}
|
||||
}
|
||||
traverse(geode);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SplitVisitor::apply(osg::Group &node)
|
||||
{
|
||||
static const std::string floorPrefix("floor_");
|
||||
const std::string &nodename = node.getName();
|
||||
if (nodename.size() >= floorPrefix.size() &&
|
||||
std::equal(floorPrefix.begin(), floorPrefix.end(), nodename.begin()))
|
||||
{
|
||||
_parts.emplace_back(&node);
|
||||
float h = 0;
|
||||
for (unsigned int i = 0; i < node.getNumDescriptions(); ++i)
|
||||
{
|
||||
QString descr = QString::fromStdString(node.getDescription(i));
|
||||
const QVector<QStringRef> descprt = descr.splitRef(QLatin1Char(';'));
|
||||
for (const QStringRef &prt : descprt)
|
||||
{
|
||||
const QVector<QStringRef> items = prt.split(QLatin1Char('='));
|
||||
if (items.size() == 2 && items[0] == QLatin1String("base_height"))
|
||||
h = items[1].toFloat();
|
||||
}
|
||||
}
|
||||
_heights.push_back(h);
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindRoomComponentsVisitor::apply(osg::Group &node)
|
||||
{
|
||||
static const std::string roomPrefix("undest_room_");
|
||||
const std::string &nodename = node.getName();
|
||||
if (nodename.size() >= roomPrefix.size() &&
|
||||
std::equal(roomPrefix.begin(), roomPrefix.end(), nodename.begin()))
|
||||
{
|
||||
//parts.push_back(&node);
|
||||
//float h = 0;
|
||||
for (unsigned int i = 0; i < node.getNumDescriptions(); ++i)
|
||||
{
|
||||
const std::string &descr = node.getDescription(i);
|
||||
std::istringstream f(descr);
|
||||
std::string s;
|
||||
while (getline(f, s, ';'))
|
||||
{
|
||||
if (s.size() != 0)
|
||||
mNamesFound.insert(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindRoomByNumberVisitor::apply(osg::Node &searchNode)
|
||||
{
|
||||
if (searchNode.getNumDescriptions() > 0)
|
||||
{
|
||||
const std::string &desc = searchNode.getDescription(0);
|
||||
size_t pos = desc.find('@');
|
||||
if (pos != std::string::npos && desc.substr(pos + 1, desc.size()) == searchForName)
|
||||
foundNodeList.push_back(&searchNode);
|
||||
}
|
||||
|
||||
traverse(searchNode);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SetWallsTransparentVisitor::SetAlpha(osg::Node *node, float alpha)
|
||||
{
|
||||
node->setNodeMask(0xFFFFFFFF);
|
||||
osg::StateSet *ss = node->getOrCreateStateSet();
|
||||
if (alpha > 0.99f)
|
||||
{
|
||||
ss->removeMode(GL_BLEND);
|
||||
ss->setRenderingHint(osg::StateSet::DEFAULT_BIN);
|
||||
/*osg::Material* mat = new osg::Material();
|
||||
mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
ss->setAttributeAndModes(mat, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
mat->setAlpha(osg::Material::FRONT_AND_BACK, 1);*/
|
||||
|
||||
ss->removeUniform("wall_color");
|
||||
}
|
||||
else if (alpha < 0.01f)
|
||||
node->setNodeMask(0x0);
|
||||
else
|
||||
{
|
||||
ss->setMode(GL_BLEND, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
osg::BlendFunc *bf = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
|
||||
ss->setAttributeAndModes(bf, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
ss->addUniform(new osg::Uniform("wall_color", osg::Vec4(1, 1, 1, alpha)));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SetWallsTransparentVisitor::apply(osg::Node &node)
|
||||
{
|
||||
std::string nm = node.getName();
|
||||
if (nm.size() > 4 && nm.substr(0, 4) == "wall")
|
||||
SetAlpha(&node, mTransparency);
|
||||
traverse(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
#pragma once
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FindByNameVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
std::vector<osg::Node *> mNodes;
|
||||
QString mName;
|
||||
explicit FindByNameVisitor(const QString &name)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mName(name)
|
||||
{}
|
||||
|
||||
void apply(osg::Node &node) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class FindExactNameVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
std::vector<osg::Node *> mNodes;
|
||||
std::set<std::string> mNamesToSearch;
|
||||
|
||||
explicit FindExactNameVisitor(const std::set<std::string> &namesToSearch)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mNamesToSearch(namesToSearch)
|
||||
{}
|
||||
|
||||
void apply(osg::Node &node) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class SplitVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
|
||||
public:
|
||||
std::vector<osg::ref_ptr<osg::Node> > _parts;
|
||||
std::vector<float> _heights;
|
||||
SplitVisitor()
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Group &node) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FindRoomComponentsVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
|
||||
public:
|
||||
std::set<std::string> mNamesFound;
|
||||
|
||||
FindRoomComponentsVisitor()
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Group &node) override;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FindRoomNamesVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
std::vector<std::string> mNames;
|
||||
|
||||
// Default constructor - initialize searchForName to "" and
|
||||
// set the traversal mode to TRAVERSE_ALL_CHILDREN
|
||||
FindRoomNamesVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Node &n) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FindRoomByNumberVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
// Default constructor - initialize searchForName to "" and
|
||||
// set the traversal mode to TRAVERSE_ALL_CHILDREN
|
||||
FindRoomByNumberVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
|
||||
searchForName()
|
||||
{}
|
||||
|
||||
// Constructor that accepts string argument
|
||||
// Initializes searchForName to user string
|
||||
// set the traversal mode to TRAVERSE_ALL_CHILDREN
|
||||
explicit FindRoomByNumberVisitor(const std::string &searchName) :
|
||||
osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
|
||||
searchForName(searchName)
|
||||
{
|
||||
}
|
||||
|
||||
void apply(osg::Node &searchNode) override;
|
||||
|
||||
// Set the searchForName to user-defined string
|
||||
void setNameToFind(const std::string &searchName)
|
||||
{
|
||||
searchForName = searchName;
|
||||
foundNodeList.clear();
|
||||
}
|
||||
|
||||
// Return a pointer to the first node in the list
|
||||
// with a matching name
|
||||
osg::Node *getFirst()
|
||||
{
|
||||
return *(foundNodeList.begin());
|
||||
}
|
||||
|
||||
|
||||
// typedef a vector of node pointers for convenience
|
||||
using NodeList = std::vector<osg::Node *>;
|
||||
|
||||
// return a reference to the list of nodes we found
|
||||
NodeList &getNodeList() { return foundNodeList; }
|
||||
|
||||
private:
|
||||
|
||||
// the name we are looking for
|
||||
std::string searchForName;
|
||||
|
||||
// List of nodes with names that match the searchForName string
|
||||
NodeList foundNodeList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class ClearVertexColorsVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
ClearVertexColorsVisitor()
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Geode &geode) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class SetWallsTransparentVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
float mTransparency;
|
||||
public:
|
||||
|
||||
explicit SetWallsTransparentVisitor(float transparency)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mTransparency(transparency)
|
||||
{
|
||||
setNodeMaskOverride(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void SetAlpha(osg::Node *node, float alpha);
|
||||
|
||||
void apply(osg::Node &node) override;
|
||||
};
|
||||
}
|
||||
+338
@@ -0,0 +1,338 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* This application is open source and may be redistributed and/or modified
|
||||
* freely and without restriction, both in commericial and non commericial applications,
|
||||
* as long as this copyright notice is maintained.
|
||||
*
|
||||
* This application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2009 Cedric Pinson
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osg/RenderInfo>
|
||||
#include <osg/GL>
|
||||
#include <osg/GLExtensions>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "windowcapturecallback.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/app/gstappsrc.h>
|
||||
#include <dtEntity/property.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void WindowCaptureCallback::operator()(osg::RenderInfo &renderInfo) const
|
||||
{
|
||||
glReadBuffer(_readBuffer);
|
||||
|
||||
osg::GraphicsContext *gc = renderInfo.getState()->getGraphicsContext();
|
||||
osg::ref_ptr<ContextData> cd = getContextData(gc);
|
||||
cd->read();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(_contextId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::WindowCaptureCallback(GLenum readBuffer, unsigned int contextid, const std::string &path, int w, int h, int framerate, int quality):
|
||||
_readBuffer(readBuffer),
|
||||
_contextId(contextid),
|
||||
_filename(path),
|
||||
_w(w),
|
||||
_h(h),
|
||||
_framerate(framerate),
|
||||
_quality(quality)
|
||||
{
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(_contextId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::ContextData *WindowCaptureCallback::createContextData(osg::GraphicsContext *gc) const
|
||||
{
|
||||
return new ContextData(gc, _readBuffer, _filename, _w, _h, _framerate, _quality);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::ContextData *WindowCaptureCallback::getContextData(osg::GraphicsContext *gc) const
|
||||
{
|
||||
osg::ref_ptr<ContextData> &data = _contextDataMap[gc];
|
||||
if (!data) data = createContextData(gc);
|
||||
|
||||
return data.get();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static gboolean bus_message(GstBus *, GstMessage *message, WindowCaptureCallback *)
|
||||
{
|
||||
switch (GST_MESSAGE_TYPE(message))
|
||||
{
|
||||
case GST_MESSAGE_WARNING:
|
||||
{
|
||||
GError *err = nullptr;
|
||||
gchar *dbg_info = nullptr;
|
||||
|
||||
gst_message_parse_warning(message, &err, &dbg_info);
|
||||
g_printerr("WARN from element %s: %s\n",
|
||||
GST_OBJECT_NAME(message->src), err->message);
|
||||
g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
|
||||
g_error_free(err);
|
||||
g_free(dbg_info);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_ERROR:
|
||||
{
|
||||
GError *err = nullptr;
|
||||
gchar *dbg_info = nullptr;
|
||||
|
||||
gst_message_parse_error(message, &err, &dbg_info);
|
||||
g_printerr("ERROR from element %s: %s\n",
|
||||
GST_OBJECT_NAME(message->src), err->message);
|
||||
g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
|
||||
g_error_free(err);
|
||||
g_free(dbg_info);
|
||||
break;
|
||||
}
|
||||
#ifdef LTS_DEBUG
|
||||
case GST_MESSAGE_PROGRESS:
|
||||
{
|
||||
GstProgressType type;
|
||||
gchar *code, *text;
|
||||
bool in_progress = false;
|
||||
|
||||
gst_message_parse_progress (message, &type, &code, &text);
|
||||
|
||||
switch (type) {
|
||||
case GST_PROGRESS_TYPE_START:
|
||||
case GST_PROGRESS_TYPE_CONTINUE:
|
||||
in_progress = true;
|
||||
break;
|
||||
case GST_PROGRESS_TYPE_COMPLETE:
|
||||
case GST_PROGRESS_TYPE_CANCELED:
|
||||
case GST_PROGRESS_TYPE_ERROR:
|
||||
in_progress = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_printerr("Progress: (%s) %s, is in progress: %d\n", code, text, in_progress);
|
||||
g_free (code);
|
||||
g_free (text);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_QOS:
|
||||
{
|
||||
gboolean live;
|
||||
guint64 running_time, stream_time, time_stamp, duration;
|
||||
gst_message_parse_qos(message, &live, &running_time, &stream_time, &time_stamp, &duration);
|
||||
g_printerr("QOS message: %d, %ld, %ld, %ld, %ld\n", live, running_time, stream_time, time_stamp, duration);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_EOS:
|
||||
g_printerr("End-Of-Stream received!n");
|
||||
break;
|
||||
case GST_MESSAGE_STATE_CHANGED:
|
||||
{
|
||||
GstState oldState, newState, pendingState;
|
||||
gst_message_parse_state_changed(message, &oldState, &newState, &pendingState);
|
||||
g_printerr("State change from %d to %d (pending: %d)\n", oldState, newState, pendingState);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_printerr("got message %s\n",
|
||||
gst_message_type_get_name(GST_MESSAGE_TYPE(message)));
|
||||
break;
|
||||
#else
|
||||
default:
|
||||
g_print("got message %s\n",
|
||||
gst_message_type_get_name(GST_MESSAGE_TYPE(message)));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return GST_BUS_PASS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::ContextData::ContextData(osg::GraphicsContext *gc, GLenum readBuffer,
|
||||
const std::string &path, int w, int h, int framerate, int quality):
|
||||
_gc(gc),
|
||||
_readBuffer(readBuffer),
|
||||
_fileName(path),
|
||||
_width(0),
|
||||
_height(0)
|
||||
{
|
||||
(void)quality;
|
||||
|
||||
_startTick = _previousFrameTick = osg::Timer::instance()->tick();
|
||||
_pboBuffer.push_back(0);
|
||||
|
||||
getSize(gc, _width, _height);
|
||||
|
||||
osg::notify(osg::INFO) << this << " Window size " << _width << ", " << _height << std::endl;
|
||||
|
||||
GstBus *bus;
|
||||
|
||||
/* Initialize GStreamer */
|
||||
gst_init(nullptr, nullptr);
|
||||
|
||||
std::ostringstream gstpipeline;
|
||||
gstpipeline << "appsrc name=\"inputsrc\" ";
|
||||
gstpipeline << "! videorate ";
|
||||
gstpipeline << "! videoscale ";
|
||||
gstpipeline << "! videoconvert ";
|
||||
gstpipeline << "! video/x-raw, width=" << w << ", height=" << h << ", framerate=" << framerate << "/1 ";
|
||||
gstpipeline << "! videoflip method=5 ";
|
||||
|
||||
//#define SHOW_DIRECTLY
|
||||
|
||||
#ifdef SHOW_DIRECTLY
|
||||
gstpipeline << "! xvimagesink ";
|
||||
#else
|
||||
gstpipeline << " ! vp9enc end-usage=cbr";
|
||||
gstpipeline << " ! webmmux ";
|
||||
gstpipeline << " ! filesink location=" << path;
|
||||
#endif
|
||||
// g_warning("pipeline: '%s'\n", gstpipeline.str().c_str());
|
||||
|
||||
/* Build the pipeline */
|
||||
_pipeline = gst_parse_launch(gstpipeline.str().c_str(), nullptr);
|
||||
|
||||
_app_source = gst_bin_get_by_name((GstBin *) _pipeline, "inputsrc");
|
||||
|
||||
bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline));
|
||||
g_assert(bus);
|
||||
|
||||
gst_bus_add_watch(bus, (GstBusFunc) bus_message, this);
|
||||
gst_object_unref(bus);
|
||||
|
||||
GstCaps *video_caps = gst_caps_new_simple("video/x-raw",
|
||||
"format", G_TYPE_STRING, "RGBA",
|
||||
"width", G_TYPE_INT, _width,
|
||||
"height", G_TYPE_INT, _height,
|
||||
"framerate", GST_TYPE_FRACTION, framerate, 1,
|
||||
nullptr);
|
||||
gst_app_src_set_caps(GST_APP_SRC(_app_source), video_caps);
|
||||
g_object_set(GST_APP_SRC(_app_source), "format", GST_FORMAT_TIME, nullptr);
|
||||
gst_caps_unref(video_caps);
|
||||
|
||||
// make gstreamer more verbose:
|
||||
g_signal_connect( _pipeline, "deep-notify", G_CALLBACK(gst_object_default_deep_notify ), nullptr );
|
||||
|
||||
/* Start playing */
|
||||
gst_element_set_state(_pipeline, GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void WindowCaptureCallback::ContextData::getSize(osg::GraphicsContext *gc, int &width, int &height)
|
||||
{
|
||||
if (gc->getTraits())
|
||||
{
|
||||
width = gc->getTraits()->width;
|
||||
height = gc->getTraits()->height;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void WindowCaptureCallback::ContextData::read()
|
||||
{
|
||||
osg::GLExtensions *ext = osg::GLExtensions::Get(_gc->getState()->getContextID(), true);
|
||||
int width = 0, height = 0;
|
||||
getSize(_gc, width, height);
|
||||
if (width != _width || _height != height)
|
||||
{
|
||||
osg::notify(osg::INFO) << this << " Window resized " << width << ", " << height << std::endl;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
unsigned int size = _width * _height * 4;
|
||||
|
||||
GLuint &pbo = _pboBuffer[0];
|
||||
|
||||
if (pbo == 0)
|
||||
{
|
||||
ext->glGenBuffers(1, &pbo);
|
||||
ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
|
||||
ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, size, nullptr, GL_STREAM_READ);
|
||||
|
||||
osg::notify(osg::INFO) << this << " Generating pbo " << pbo << std::endl;
|
||||
}
|
||||
else
|
||||
ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
|
||||
|
||||
osg::Timer_t tick_now = osg::Timer::instance()->tick();
|
||||
|
||||
glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
GLubyte *src = (GLubyte *)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
|
||||
GL_READ_ONLY_ARB);
|
||||
if (src)
|
||||
{
|
||||
guint64 timestamp = (tick_now - _startTick) * 1000;
|
||||
guint64 duration = (tick_now - _previousFrameTick) * 1000;
|
||||
GstBuffer *buffer = gst_buffer_new_allocate(nullptr, size, nullptr);
|
||||
GstMapInfo info;
|
||||
gst_buffer_map(buffer, &info, GST_MAP_WRITE);
|
||||
memcpy(info.data, src, size);
|
||||
gst_buffer_unmap(buffer, &info);
|
||||
GST_BUFFER_PTS(buffer) = timestamp;
|
||||
GST_BUFFER_DTS(buffer) = timestamp;
|
||||
GST_BUFFER_DURATION(buffer) = duration;
|
||||
_previousFrameTick = tick_now;
|
||||
|
||||
GstFlowReturn ret;
|
||||
g_signal_emit_by_name(_app_source, "push-buffer", buffer, &ret);
|
||||
gst_buffer_unref(buffer);
|
||||
|
||||
if (ret != GST_FLOW_OK)
|
||||
{
|
||||
// some error, stop sending data
|
||||
GST_DEBUG("some error");
|
||||
}
|
||||
|
||||
ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
}
|
||||
|
||||
ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::ContextData::~ContextData()
|
||||
{
|
||||
gboolean ret = gst_element_send_event(_pipeline, gst_event_new_eos());
|
||||
if (ret)
|
||||
{
|
||||
GstMessageType types = GST_MESSAGE_EOS;
|
||||
GstMessage *msg = gst_bus_timed_pop_filtered(GST_ELEMENT_BUS(_pipeline), GST_CLOCK_TIME_NONE, types);
|
||||
gst_message_unref(msg);
|
||||
}
|
||||
gst_element_set_state(_pipeline, GST_STATE_NULL);
|
||||
gst_object_unref(_pipeline);
|
||||
}
|
||||
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* This application is open source and may be redistributed and/or modified
|
||||
* freely and without restriction, both in commericial and non commericial applications,
|
||||
* as long as this copyright notice is maintained.
|
||||
*
|
||||
* This application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2009 Cedric Pinson
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <osg/Camera>
|
||||
|
||||
// fwd decl for gstreamer objects
|
||||
struct _GstElement;
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class WindowCaptureCallback : public osg::Camera::DrawCallback
|
||||
{
|
||||
public:
|
||||
struct ContextData : public osg::Referenced
|
||||
{
|
||||
ContextData(osg::GraphicsContext *gc, GLenum readBuffer, const std::string &path, int w, int h, int framerate, int quality);
|
||||
~ContextData();
|
||||
|
||||
static void getSize(osg::GraphicsContext *gc, int &width, int &height);
|
||||
|
||||
void read();
|
||||
|
||||
osg::GraphicsContext *_gc;
|
||||
GLenum _readBuffer;
|
||||
std::string _fileName;
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
|
||||
std::vector< GLuint > _pboBuffer;
|
||||
|
||||
osg::Timer_t _previousFrameTick;
|
||||
osg::Timer_t _startTick;
|
||||
_GstElement *_pipeline;
|
||||
_GstElement *_app_source;
|
||||
};
|
||||
|
||||
WindowCaptureCallback(GLenum readBuffer, unsigned int contextid, const std::string &path, int w, int h, int framerate, int quality);
|
||||
~WindowCaptureCallback() = default;
|
||||
|
||||
ContextData *createContextData(osg::GraphicsContext *gc) const;
|
||||
ContextData *getContextData(osg::GraphicsContext *gc) const;
|
||||
void operator()(osg::RenderInfo &renderInfo) const override;
|
||||
|
||||
using ContextDataMap = std::map<osg::GraphicsContext *, osg::ref_ptr<ContextData> >;
|
||||
|
||||
GLenum _readBuffer;
|
||||
unsigned int _contextId;
|
||||
std::string _filename;
|
||||
int _w;
|
||||
int _h;
|
||||
int _framerate;
|
||||
int _quality;
|
||||
mutable ContextDataMap _contextDataMap;
|
||||
};
|
||||
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Created by Mike Wille, SLSE, 2017-08-17
|
||||
#
|
||||
|
||||
FIND_PACKAGE(BgViewer REQUIRED)
|
||||
SET(_ver 3.4.1)
|
||||
IF (WIN32)
|
||||
SET(_ver 3.4.0)
|
||||
ENDIF()
|
||||
FIND_PACKAGE(OpenSceneGraph ${_ver} REQUIRED osgViewer osgDB osgQt osgText osgUtil)
|
||||
FIND_PACKAGE(OpenGL REQUIRED)
|
||||
|
||||
SET(BuildingViewerCommon_SRCS
|
||||
bdv_bgviewer_widget_container.cpp
|
||||
bdv_bgviewer_widget_container.h
|
||||
bdv_communication_interface_internal.cpp
|
||||
bdv_communication_interface_internal.h
|
||||
bdv_controller.cpp
|
||||
bdv_controller.h
|
||||
bdv_dds_controller.cpp
|
||||
bdv_dds_controller.h
|
||||
bdv_helper.cpp
|
||||
bdv_helper.h
|
||||
bdv_plugin_provider.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
|
||||
BgViewer/viewerCtrl/buildingmanager.cpp
|
||||
BgViewer/viewerCtrl/buildingmanager.h
|
||||
BgViewer/viewerCtrl/buildingmanager.h
|
||||
BgViewer/viewerCtrl/cameraviewposition.h
|
||||
BgViewer/viewerCtrl/iconcomponent.cpp
|
||||
BgViewer/viewerCtrl/iconcomponent.h
|
||||
BgViewer/viewerCtrl/mainloop.cpp
|
||||
BgViewer/viewerCtrl/mainloop.h
|
||||
BgViewer/viewerCtrl/messages.cpp
|
||||
BgViewer/viewerCtrl/messages.h
|
||||
BgViewer/viewerCtrl/modelsplittercomponent.cpp
|
||||
BgViewer/viewerCtrl/modelsplittercomponent.h
|
||||
BgViewer/viewerCtrl/motionmodel.cpp
|
||||
BgViewer/viewerCtrl/motionmodel.h
|
||||
BgViewer/viewerCtrl/orthomotionmodel.cpp
|
||||
BgViewer/viewerCtrl/orthomotionmodel.h
|
||||
BgViewer/viewerCtrl/playercomponent.cpp
|
||||
BgViewer/viewerCtrl/playercomponent.h
|
||||
BgViewer/viewerCtrl/roomdestructioncomponent.cpp
|
||||
BgViewer/viewerCtrl/roomdestructioncomponent.h
|
||||
BgViewer/viewerCtrl/textcomponent.cpp
|
||||
BgViewer/viewerCtrl/textcomponent.h
|
||||
BgViewer/viewerCtrl/viewerinterface.h
|
||||
BgViewer/viewerCtrl/viewerinterfaceimpl.cpp
|
||||
BgViewer/viewerCtrl/viewerinterfaceimpl.h
|
||||
BgViewer/viewerCtrl/viewermainwindow.cpp
|
||||
BgViewer/viewerCtrl/viewermainwindow.h
|
||||
BgViewer/viewerCtrl/viewwidget.cpp
|
||||
BgViewer/viewerCtrl/viewwidget.h
|
||||
BgViewer/viewerCtrl/viewwidgetcontainer.cpp
|
||||
BgViewer/viewerCtrl/viewwidgetcontainer.h
|
||||
BgViewer/viewerCtrl/viewwidgetstate.h
|
||||
BgViewer/viewerCtrl/visitors.cpp
|
||||
BgViewer/viewerCtrl/visitors.h
|
||||
)
|
||||
|
||||
IF (NOT WIN32)
|
||||
FIND_PACKAGE(PkgConfig)
|
||||
pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
|
||||
pkg_check_modules(GSTREAMER_APP REQUIRED gstreamer-app-1.0)
|
||||
|
||||
LIST(APPEND BuildingViewerCommon_SRCS
|
||||
BgViewer/viewerCtrl/videocomponent.cpp
|
||||
BgViewer/viewerCtrl/videocomponent.h
|
||||
BgViewer/viewerCtrl/windowcapturecallback.cpp
|
||||
BgViewer/viewerCtrl/windowcapturecallback.h
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
NGL_WRAP_UI(BuildingViewerCommon_SRCS
|
||||
BgViewer/viewerCtrl/viewwidget.ui
|
||||
)
|
||||
INSTALL_SHARED_FILES(BuildingViewerCommon_SRCS
|
||||
FILES shaders/roomdestruction.frag shaders/roomdestruction.vert
|
||||
DESTINATION BuildingViewer/shaders
|
||||
WS
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(WS BuildingViewerCommon SHARED ${BuildingViewerCommon_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(BuildingViewerCommon
|
||||
PRIVATE
|
||||
Qt5::OpenGL
|
||||
${OPENGL_LIBRARIES}
|
||||
${BGVIEWER_DTENTITYOSG_LIBRARY}
|
||||
${BGVIEWER_DTENTITY_LIBRARY}
|
||||
${OPENTHREADS_LIBRARIES} # FIND_PACKAGE(OpenSceneGraph)
|
||||
${OPENSCENEGRAPH_LIBRARIES} # FIND_PACKAGE(OpenSceneGraph)
|
||||
)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(BuildingViewerCommon
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BgViewer/dtEntity/ext/RapidXML
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/BgViewer/viewerCtrl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../share
|
||||
${OSG_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
IF (NOT WIN32)
|
||||
NGL_SET_TARGET_PROPERTIES(BuildingViewerCommon PROPERTIES DEFINE_SYMBOL BUILD_WITH_GSTREAMER)
|
||||
NGL_TARGET_LINK_LIBRARIES(BuildingViewerCommon
|
||||
PRIVATE
|
||||
${GSTREAMER_LIBRARIES}
|
||||
${GSTREAMER_APP_LIBRARIES}
|
||||
)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(BuildingViewerCommon
|
||||
PRIVATE
|
||||
${GSTREAMER_INCLUDE_DIRS}
|
||||
${GSTREAMER_APP_INCLUDE_DIRS}
|
||||
)
|
||||
ENDIF()
|
||||
NGL_ADD_COMPILE_FLAGS(BuildingViewerCommon -DVIEWER_CTRL_LIBRARY_STATIC)
|
||||
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(BuildingViewerCommon
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(BuildingViewerCommon
|
||||
PRIVATE
|
||||
ngltools
|
||||
LtsPluginManager
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
AsbDataPluginInterface
|
||||
AvmDataPluginInterface
|
||||
BldDataPluginInterface
|
||||
AesDataPluginInterface
|
||||
SrpDataPluginInterface
|
||||
IsmDataPluginInterface
|
||||
PpmDataPluginInterface
|
||||
PpmParticipantInfoGuiPluginInterface
|
||||
IsmShared
|
||||
LtsAppManager
|
||||
LtsCoordTrans
|
||||
LtsSessionData
|
||||
LtsSession
|
||||
LtsWidgets
|
||||
LtsUtilsSettings
|
||||
LtsUtilsGuiDds
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(BuildingViewerCommon)
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, NLSE, 2018-03-29
|
||||
*/
|
||||
#include "bdv_bgviewer_widget_container.h"
|
||||
#include <QGridLayout>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerWidgetContainer::BgViewerWidgetContainer(QWidget *pBgViewerWidget)
|
||||
: QWidget()
|
||||
, m_pBgViewerWidget(pBgViewerWidget)
|
||||
{
|
||||
auto gl = new QGridLayout(this);
|
||||
gl->setContentsMargins(QMargins());
|
||||
gl->setSpacing(0);
|
||||
if (m_pBgViewerWidget)
|
||||
gl->addWidget(m_pBgViewerWidget);
|
||||
}
|
||||
|
||||
|
||||
BgViewerWidgetContainer::~BgViewerWidgetContainer()
|
||||
{
|
||||
if (m_pBgViewerWidget)
|
||||
{
|
||||
layout()->removeWidget(m_pBgViewerWidget);
|
||||
m_pBgViewerWidget->setParent(nullptr); // Removing is not sufficient, we also have to reset the parent to prevent deletion
|
||||
emit signalWidgetReleased();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, NLSE, 2018-03-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
/*
|
||||
* Purpose: The capture/stolen BgViewer widget may be used within a LtsDialog
|
||||
* by accessing it via 'BgViewerControllerSingleton::getBgViewerWidget()'.
|
||||
* To prevent the deletion of 'pBgViewerWidget' we return this container whose
|
||||
* dtor avoids a deletion.
|
||||
*/
|
||||
class BgViewerWidgetContainer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BgViewerWidgetContainer(QWidget *pBgViewerWidget);
|
||||
~BgViewerWidgetContainer();
|
||||
|
||||
signals:
|
||||
void signalWidgetReleased();
|
||||
|
||||
private:
|
||||
QPointer<QWidget> m_pBgViewerWidget;
|
||||
};
|
||||
}
|
||||
+655
@@ -0,0 +1,655 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-08-15
|
||||
*/
|
||||
#include "bdv_communication_interface_internal.h"
|
||||
#include <QTimer>
|
||||
#include <cassert>
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
static const char PLAYER_PREFIX[] = "player_";
|
||||
static const char ROOM_PREFIX[] = "";
|
||||
static const char BUILDING_PREFIX[] = "House_";
|
||||
//static const char CAMERA_PREFIX[] = "Camera_";
|
||||
|
||||
static inline std::string createPlayerIdString(int playerId)
|
||||
{
|
||||
return PLAYER_PREFIX + std::to_string(playerId);
|
||||
}
|
||||
|
||||
static inline std::string createBuildingIdString(int buildingId)
|
||||
{
|
||||
return BUILDING_PREFIX + std::to_string(buildingId);
|
||||
}
|
||||
|
||||
static inline std::string createRoomNumberString(int roomNumber)
|
||||
{
|
||||
return ROOM_PREFIX + std::to_string(roomNumber);
|
||||
}
|
||||
|
||||
CommunicationInterfaceInternal::CommunicationInterfaceInternal(VCtrl::ViewerInterface* pviewerInterface)
|
||||
: m_pviewerInterface(pviewerInterface)
|
||||
, m_logger(getLogger("CommunicationInterface"))
|
||||
{
|
||||
assert(m_pviewerInterface);
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::playerCreate(int playerID, int partyID, const QString &strPathToSymbolFile,
|
||||
const LtsUtils::QPoint3D &pos, int buildingID, int roomNumber, Core::PositionReportingSource reportingSource)
|
||||
{
|
||||
std::string playerIdStr = createPlayerIdString(playerID);
|
||||
VCtrl::Color partyColor = m_teamMap.value(partyID).color;
|
||||
m_pviewerInterface->CreatePlayer(playerIdStr, strPathToSymbolFile.toStdString(), partyColor);
|
||||
|
||||
std::string buildingIdStr, roomNumberStr;
|
||||
if (buildingID > 0)
|
||||
{
|
||||
buildingIdStr = createBuildingIdString(buildingID);
|
||||
}
|
||||
if (roomNumber > 0)
|
||||
{
|
||||
roomNumberStr = createRoomNumberString(roomNumber);
|
||||
}
|
||||
|
||||
const VCtrl::Vec3d tgt(pos.x(), pos.y(), pos.z());
|
||||
m_pviewerInterface->Teleport(playerIdStr, 0, tgt, buildingIdStr, roomNumber, roomNumberStr,
|
||||
(reportingSource == Core::PositionReportingSource::Wls
|
||||
? VCtrl::ZValue::AboveMsl
|
||||
: VCtrl::ZValue::RelativeBuildings));
|
||||
m_pviewerInterface->SetPlayerShown(playerIdStr, true, 0);
|
||||
|
||||
m_playerId2String[playerID] = playerIdStr;
|
||||
m_string2PlayerId[playerIdStr] = playerID;
|
||||
m_player2TeamMap[playerID] = partyID;
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::playerPlace(int playerID, const LtsUtils::QPoint3D &pos,
|
||||
int buildingID, int roomNumber, Core::PositionReportingSource reportingSource)
|
||||
{
|
||||
auto it = m_playerId2String.find(playerID);
|
||||
if (it == m_playerId2String.end())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Trying to set player position for unknown (=not created) player with id " << playerID;
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string &playerIdStr = it.value();
|
||||
|
||||
std::string buildingIdStr, roomNumberStr;
|
||||
if (buildingID > 0 )
|
||||
{
|
||||
buildingIdStr = createBuildingIdString(buildingID);
|
||||
}
|
||||
if ( roomNumber > 0)
|
||||
{
|
||||
roomNumberStr = createRoomNumberString(roomNumber);
|
||||
}
|
||||
|
||||
const VCtrl::Vec3d tgt(pos.x(), pos.y(), pos.z());
|
||||
m_pviewerInterface->Teleport(playerIdStr, 0, tgt, buildingIdStr, roomNumber, roomNumberStr,
|
||||
(reportingSource == Core::PositionReportingSource::Wls
|
||||
? VCtrl::ZValue::AboveMsl
|
||||
: VCtrl::ZValue::RelativeBuildings));
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::playerDelete(int playerID)
|
||||
{
|
||||
if (playerID <= 0)
|
||||
return;
|
||||
std::string playerIdStr = createPlayerIdString(playerID);
|
||||
m_pviewerInterface->DeletePlayer(playerIdStr);
|
||||
|
||||
m_playerId2String.remove(playerID);
|
||||
m_string2PlayerId.remove(playerIdStr);
|
||||
m_player2TeamMap.remove(playerID);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::setPlayerVisible(int playerID, bool bVisible)
|
||||
{
|
||||
if (playerID <= 0)
|
||||
return;
|
||||
std::string playerIdStr = createPlayerIdString(playerID);
|
||||
m_pviewerInterface->SetPlayerShown(playerIdStr, bVisible);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::playerClear()
|
||||
{
|
||||
const auto string2PlayerId_Copy = m_string2PlayerId;
|
||||
for (const int playerId : string2PlayerId_Copy)
|
||||
playerDelete(playerId);
|
||||
|
||||
m_player2TeamMap.clear();
|
||||
m_playerId2String.clear();
|
||||
m_string2PlayerId.clear();
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::playerUpdateSymbols()
|
||||
{
|
||||
m_pviewerInterface->reloadPlayerIcons();
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::playerUpdatePlayerSymbol(int playerID, const QString &strPathToSymbolFile)
|
||||
{
|
||||
std::string playerIdStr = createPlayerIdString(playerID);
|
||||
m_pviewerInterface->SetPlayerIcon(playerIdStr, strPathToSymbolFile.toStdString());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Also causes the reload the symbol file for playerIdDst.
|
||||
* Hence, the new symbol file needs to be created before calling this function.
|
||||
*/
|
||||
void CommunicationInterfaceInternal::playerHit(const int32_t id, int playerIdSrc, int playerIdDst,
|
||||
const LtsUtils::QPoint3D &posSrc, const LtsUtils::QPoint3D &posDst,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst,
|
||||
int lineType, int64_t time)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "playerHit id= " << id;
|
||||
const std::string playerIdStrDst = m_playerId2String.value(playerIdDst);
|
||||
const std::string playerIdStrSrc = m_playerId2String.value(playerIdSrc);
|
||||
const VCtrl::Vec3d src(posSrc.x(), posSrc.y(), posSrc.z());
|
||||
const VCtrl::Vec3d dst(posDst.x(), posDst.y(), posDst.z());
|
||||
m_pviewerInterface->Shoot(id, playerIdStrSrc, playerIdStrDst,
|
||||
src, dst,
|
||||
buildingIdSrc, roomNumberSrc, buildingIdDst, roomNumberDst,
|
||||
lineType, time / 1000.);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::buildingHit(const int32_t id, int buildingId, int damagePercent, const QMap<int,int>& mapRoomDestructions)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "buildingHit for building " << buildingId
|
||||
<< " id=" << id
|
||||
<< " damagePercent " << damagePercent
|
||||
<< " roomlist size: " << mapRoomDestructions.size();
|
||||
|
||||
const std::string buildingIdStr = createBuildingIdString(buildingId);
|
||||
|
||||
// Nur bei ganz zersört oder gar nicht zerstört auch die buildingDestruction setzen da diese alle Räume beeinflusst
|
||||
if (damagePercent <= 0 || damagePercent >= 80)
|
||||
{
|
||||
if (damagePercent >= 80)
|
||||
damagePercent = 100;
|
||||
m_pviewerInterface->SetBuildingDestructionValue(buildingIdStr, damagePercent / 100.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto it = mapRoomDestructions.begin(); it != mapRoomDestructions.end(); ++it)
|
||||
{
|
||||
const int roomNumber = it.key();
|
||||
DEBUG_LOG(m_logger) << "BuildingId " << buildingId
|
||||
<< ", room: "<< roomNumber
|
||||
<< ", destruction: " << it.value();
|
||||
std::string roomNumberStr = createRoomNumberString(roomNumber);
|
||||
if (!m_pviewerInterface->SetRoomDestructionValue(buildingIdStr, roomNumberStr,it.value() / 100.f))
|
||||
ERROR_LOG(m_logger) << "SetRoomDestructionValue failed for room "<< roomNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::roomHit(const int32_t id, int playerIdSrc, int buildingId, int roomNumber, const LtsUtils::QPoint3D &posSrc, int lineType, int64_t time)
|
||||
{
|
||||
// ERROR_LOG(m_logger) << "HOTLINE roomHit for building " << buildingId
|
||||
//<< " id=" << id;
|
||||
|
||||
const std::string playerIdStrSrc = m_playerId2String.value(playerIdSrc);
|
||||
const std::string buildingIdStrDst = createBuildingIdString(buildingId);
|
||||
const std::string roomNumberStrDst = createRoomNumberString(roomNumber);
|
||||
const VCtrl::Vec3d src(posSrc.x(), posSrc.y(), posSrc.z());
|
||||
|
||||
DEBUG_LOG(m_logger) << "roomHit for building palyer " << playerIdStrSrc
|
||||
<< " building " << buildingIdStrDst
|
||||
<< " room " << roomNumberStrDst
|
||||
<< " id=" << id;
|
||||
|
||||
|
||||
m_pviewerInterface->Shoot(id, playerIdStrSrc, buildingIdStrDst, roomNumberStrDst, src, lineType, time / 1000.);
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::removeRoomHit(const int32_t id)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "removeRoomHit id=" << id;
|
||||
m_pviewerInterface->removeShoot(id);
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::setTeamConfiguration(const QMap<qint32, ParticipantManagement::Party> &parties)
|
||||
{
|
||||
for (const ParticipantManagement::Party &party : parties)
|
||||
{
|
||||
BdvParty bdvParty;
|
||||
bdvParty.id = party.id();
|
||||
bdvParty.name = ParticipantManagement::trPartyName(party.name());
|
||||
|
||||
const uint32_t argb = party.color();
|
||||
bdvParty.color.w = ( ( ( argb >> 24 ) & 0xff ) / 255.);
|
||||
bdvParty.color.x = ( ( ( argb >> 16 ) & 0xff ) / 255.);
|
||||
bdvParty.color.y = ( ( ( argb >> 8 ) & 0xff ) / 255.);
|
||||
bdvParty.color.z = ( ( ( argb >> 0 ) & 0xff ) / 255.);
|
||||
m_teamMap[bdvParty.id] = bdvParty;
|
||||
}
|
||||
|
||||
std::map<std::string, VCtrl::Color> mapPlayerColors;
|
||||
for (auto it = m_player2TeamMap.cbegin(); it != m_player2TeamMap.cend(); ++it)
|
||||
{
|
||||
const auto itParty = m_teamMap.constFind(it.value());
|
||||
if (itParty == m_teamMap.cend())
|
||||
continue;
|
||||
mapPlayerColors.emplace(std::make_pair(createPlayerIdString(it.key()),
|
||||
itParty.value().color));
|
||||
}
|
||||
m_pviewerInterface->UpdatePlayerPartyColors(mapPlayerColors);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::systemSetSimulationTime(qint64 time)
|
||||
{
|
||||
double tSimTime = time / 1000;
|
||||
double tCurSimTime = m_pviewerInterface->GetSimulationTime();
|
||||
if(fabs(tCurSimTime - tSimTime) < 0.5)
|
||||
return;
|
||||
m_pviewerInterface->SetSimulationTime(tSimTime);
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::setSimuationPace(double pace)
|
||||
{
|
||||
m_pviewerInterface->SetTimeScale(pace);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::systemDisconnect()
|
||||
{
|
||||
playerClear();
|
||||
clearCameras();
|
||||
systemSetPaused(true);
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::systemSetPaused(bool bPaused)
|
||||
{
|
||||
m_pviewerInterface->SetPaused(bPaused);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::systemSetMountingPoint(const InfrastructureManagement::MountingPoint &data, const QString &filename, bool show)
|
||||
{
|
||||
int buildingId = data.buildingId();
|
||||
const QString &mountingPointName = filename;
|
||||
double x = data.relPosition().offsetX();
|
||||
double y = data.relPosition().offsetY();
|
||||
double z = data.relPosition().offsetZ();
|
||||
|
||||
const std::string buildingIdStr = createBuildingIdString(buildingId);
|
||||
|
||||
if(!show)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Hiding mounting point \"" << mountingPointName<< "\"";
|
||||
m_pviewerInterface->HideDeviceIcon(mountingPointName.toStdString());
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_deviceMap.contains(mountingPointName))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Trying to add a mounting point which was already added - trying to re-add";
|
||||
//remove first and then reAdd
|
||||
m_pviewerInterface->HideDeviceIcon(mountingPointName.toStdString());
|
||||
}
|
||||
|
||||
const VCtrl::Vec3d position(x,y,z);
|
||||
if(m_pviewerInterface->ShowDeviceIcon(mountingPointName.toStdString(), buildingIdStr, position, filename.toStdString())) {
|
||||
DEBUG_LOG(m_logger) << "Added mounting point to scene: " << mountingPointName;
|
||||
m_deviceMap[mountingPointName] = DeviceInfo(buildingId, mountingPointName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excStartRecording(const QString& strPathOutputFolder, const QString &buildingId, int w, int h, int framerate, int quality)
|
||||
{
|
||||
m_pviewerInterface->StartVideoRecording(buildingId.toStdString(), strPathOutputFolder.toStdString(), w, h, framerate, quality);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excStopRecording(const QString &buildingId)
|
||||
{
|
||||
m_pviewerInterface->StopVideoRecording(buildingId.toStdString());
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excConnect(const std::vector<std::string> &paths, const QString &strXMLFile)
|
||||
{
|
||||
m_pviewerInterface->SetProjectDataPaths(paths);
|
||||
m_pviewerInterface->LoadBuildingPositionMap(strXMLFile.toStdString(), (strXMLFile.size() ? false : true));
|
||||
emit signalBgViewerInitFinished();
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excDeleteBuildingList()
|
||||
{
|
||||
m_pviewerInterface->LoadBuildingPositionMap(std::string(), false);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excSetHitlineDuration(uint32_t duration_s)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "excSetHitlineDuration=" << duration_s;
|
||||
m_pviewerInterface->setHitLineDuration(duration_s);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excUseExactPositioning(bool useExactPositioning)
|
||||
{
|
||||
m_useExactPositioning = useExactPositioning;
|
||||
m_pviewerInterface->UseExactPositioning(useExactPositioning);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excOpenView(const std::vector<std::string> &bldIds)
|
||||
{
|
||||
m_pviewerInterface->openViews(bldIds, m_useExactPositioning);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excCloseView(const std::vector<std::string> &bldIds)
|
||||
{
|
||||
m_pviewerInterface->closeViews(bldIds);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excCloseAllViews()
|
||||
{
|
||||
m_pviewerInterface->closeViews({"all"});
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excHighlightView(const QString &buildingId)
|
||||
{
|
||||
m_pviewerInterface->highlightView(buildingId.toStdString());
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excGetBuildingList()
|
||||
{
|
||||
const auto states = m_pviewerInterface->getBuildingState();
|
||||
QVector<BuildingTuple> tplStates;
|
||||
BuildingTuple tpl;
|
||||
tplStates.reserve(states.size());
|
||||
for (const auto &state : states)
|
||||
{
|
||||
tpl.buildingId = QString::fromStdString(state.buildingId);
|
||||
tpl.description = QString::fromStdString(state.description);
|
||||
tpl.entityId = state.entityId;
|
||||
tpl.isShown = state.isShown;
|
||||
tplStates += tpl;
|
||||
}
|
||||
emit signalReceivedBuildingList(tplStates);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excSetGlobalTransparency(double transparency)
|
||||
{
|
||||
m_pviewerInterface->setTransparency(transparency / 100.0);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excSetGlobalViewMode(bool useOrtho)
|
||||
{
|
||||
m_pviewerInterface->setViewMode(useOrtho ? VCtrl::ViewMode::ORTHOGRAPHIC : VCtrl::ViewMode::ISOMETRIC);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excSetGlobalDotsMode(bool useDots)
|
||||
{
|
||||
m_pviewerInterface->setDisplayMode(useDots ? VCtrl::PlayerDisplayMode::Dots : VCtrl::PlayerDisplayMode::Icons);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excRestoreViewState(const QJsonValue &val)
|
||||
{
|
||||
m_pviewerInterface->setViewState(val);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::excGetViewState()
|
||||
{
|
||||
const auto state = m_pviewerInterface->getViewState();
|
||||
emit signalReceivedViewState(state);
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::excSetBuildingDisplayName(const QString &buildingId, const QString &strBuildingDisplayName)
|
||||
{
|
||||
m_pviewerInterface->setBuildingDisplayName(buildingId.toStdString(), strBuildingDisplayName.toStdString());
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::excSetRoomDisplayName(const QString &strFeatureID, const QString &strRoomName, const QString &strRoomDisplayName)
|
||||
{
|
||||
m_pviewerInterface->SetDisplayName(strFeatureID.toStdString(), strRoomName.toStdString(), strRoomDisplayName.toStdString());
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::extSetMountingPointAsset(const QString &strFeatureID, const QString &strMountingPointId,
|
||||
const QVector3D& position, BuildingViewer::AssetTypes assetType)
|
||||
{
|
||||
m_pviewerInterface->setMountingPointAsset({strFeatureID.toStdString(),
|
||||
strMountingPointId.toStdString(),
|
||||
{position.x(), position.y(), position.z()},
|
||||
assetType});
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::extHideMountingPointAsset(const QString &strMountingPointId)
|
||||
{
|
||||
m_pviewerInterface->HideDeviceIcon(strMountingPointId.toStdString());
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::clearCameras()
|
||||
{
|
||||
for (const DeviceInfo &di : qAsConst(m_deviceMap))
|
||||
{
|
||||
if (!di.deviceName.startsWith(QLatin1String("Camera")))
|
||||
continue;
|
||||
if (!m_pviewerInterface->HideDeviceIcon(di.deviceName.toStdString()))
|
||||
ERROR_LOG(m_logger) << "Could not remove camera with id " << di.deviceName;
|
||||
}
|
||||
m_deviceMap.clear();
|
||||
}
|
||||
|
||||
|
||||
// VCtrl::ViewerCallback interface
|
||||
void CommunicationInterfaceInternal::SystemReady()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::TransformChanged(const std::string &id, const VCtrl::Vec3d &pos, const VCtrl::Quat &attitude)
|
||||
{
|
||||
Q_UNUSED(id);
|
||||
Q_UNUSED(pos);
|
||||
Q_UNUSED(attitude);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::NavMeshGroupChanged(const std::string &id, const std::string &grpname)
|
||||
{
|
||||
Q_UNUSED(id);
|
||||
Q_UNUSED(grpname);
|
||||
}
|
||||
|
||||
|
||||
static inline bool isPlayerId(const std::string &playerIdString, int *playerId)
|
||||
{
|
||||
const QString playerIdQString(QString::fromStdString(playerIdString));
|
||||
bool bOk = false;
|
||||
if (playerIdQString.startsWith(QLatin1String(PLAYER_PREFIX)))
|
||||
*playerId = playerIdQString.midRef(QLatin1String(PLAYER_PREFIX).size()).toInt(&bOk);
|
||||
return bOk;
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::PlayerPicked(const std::string &strId)
|
||||
{
|
||||
int playerId = 0;
|
||||
if (isPlayerId(strId, &playerId)) {
|
||||
emit signalPlayerPicked(playerId);
|
||||
} else {
|
||||
// asset string may be, e.g., "House_56_MountingPoint_37"
|
||||
QString str = QString::fromStdString(strId);
|
||||
int structureElementId = str.remove(0, str.lastIndexOf(QStringLiteral("_")) + 1).toInt();
|
||||
INFO_LOG(m_logger) << "Picked mounting point with id " << strId
|
||||
<< " mountingPointId=" << structureElementId;
|
||||
if(structureElementId < 0) {
|
||||
WARNING_LOG(m_logger) << "Picked mounting point with id " << strId;
|
||||
return;
|
||||
}
|
||||
|
||||
emit signalAssetPicked(structureElementId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::DisplayNamePicked(const std::string &buildingid, const std::string &roomname)
|
||||
{
|
||||
// HandleViewerEvent (see below) handles this...
|
||||
Q_UNUSED(buildingid);
|
||||
Q_UNUSED(roomname);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::ViewCreated(unsigned int contextId, VCtrl::ViewMode viewmode)
|
||||
{
|
||||
Q_UNUSED(contextId);
|
||||
Q_UNUSED(viewmode);
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::ViewModeChanged(unsigned int contextId, VCtrl::ViewMode viewmode)
|
||||
{
|
||||
Q_UNUSED(contextId);
|
||||
Q_UNUSED(viewmode);
|
||||
emit signalViewerEventButton();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::ViewLineModeChanged(unsigned int contextId, bool line)
|
||||
{
|
||||
Q_UNUSED(contextId);
|
||||
Q_UNUSED(line);
|
||||
emit signalViewerEventButton();
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::ViewNameModeChanged(unsigned int contextId, bool name)
|
||||
{
|
||||
Q_UNUSED(contextId);
|
||||
Q_UNUSED(name);
|
||||
emit signalViewerEventButton();
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::ViewLockRotationChanged(unsigned int contextId, bool lock)
|
||||
{
|
||||
Q_UNUSED(contextId);
|
||||
Q_UNUSED(lock);
|
||||
emit signalViewerEventButton();
|
||||
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::ViewTransparencyChanged()
|
||||
{
|
||||
emit signalViewerEventButton();
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::PlayerDisplayModeChanged(unsigned int contextId, VCtrl::PlayerDisplayMode mode)
|
||||
{
|
||||
Q_UNUSED(contextId);
|
||||
Q_UNUSED(mode);
|
||||
emit signalViewerEventButton();
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::ViewClosed(unsigned int contextId)
|
||||
{
|
||||
Q_UNUSED(contextId);
|
||||
}
|
||||
|
||||
|
||||
void CommunicationInterfaceInternal::HandleViewerEvent(BgViewerEvents event, const std::vector<std::string> &args)
|
||||
{
|
||||
if (args.size() < 1)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const QString featureID = QString::fromStdString(args[0]);
|
||||
switch (event)
|
||||
{
|
||||
case BuildingViewer::BgViewerEvents::WidgetClosed:
|
||||
emit signalViewerEventWidgetClosed(featureID);
|
||||
break;
|
||||
case BuildingViewer::BgViewerEvents::WidgetMaximized:
|
||||
emit signalViewerEventWidgetMaximized(featureID);
|
||||
break;
|
||||
case BuildingViewer::BgViewerEvents::WidgetMinimized:
|
||||
emit signalViewerEventWidgetMinimized(featureID);
|
||||
break;
|
||||
case BuildingViewer::BgViewerEvents::WidgetGotFocus:
|
||||
emit signalViewerEventWidgetFocused(featureID);
|
||||
break;
|
||||
case BuildingViewer::BgViewerEvents::RoomNameClicked:
|
||||
{
|
||||
if (args.size() >= 2)
|
||||
{
|
||||
const QString roomID = QString::fromStdString(args[1]);
|
||||
emit signalViewerEventRoomNameClicked(featureID, roomID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::ViewZoomChanged(const std::string &buildingId, double top, double left, double bottom, double right)
|
||||
{
|
||||
emit signalViewerZoomChanged(QString::fromStdString(buildingId), top, left, bottom, right);
|
||||
}
|
||||
|
||||
void CommunicationInterfaceInternal::LogMessage(Severity &severity, const std::string &filename, const std::string &methodname, int linenumber, const std::string &msg)
|
||||
{
|
||||
auto logLevel = NGL::LogLevel::Info;
|
||||
bool logAlways = false;
|
||||
switch (severity)
|
||||
{
|
||||
case Severity::Always:
|
||||
logAlways = true;
|
||||
logLevel = NGL::LogLevel::Info;
|
||||
break;
|
||||
case Severity::Debug:
|
||||
logLevel = NGL::LogLevel::Debug;
|
||||
break;
|
||||
case Severity::Info:
|
||||
logLevel = NGL::LogLevel::Info;
|
||||
break;
|
||||
case Severity::Warning:
|
||||
logLevel = NGL::LogLevel::Warning;
|
||||
break;
|
||||
case Severity::Error:
|
||||
logLevel = NGL::LogLevel::Error;
|
||||
break;
|
||||
case Severity::Fatal:
|
||||
logLevel = NGL::LogLevel::Fatal;
|
||||
break;
|
||||
}
|
||||
if (logAlways || m_logger.isLevelEnabled(logLevel))
|
||||
NGL::LogStreamHelper(m_logger, logLevel, filename.c_str(), linenumber, methodname.c_str()) << msg;
|
||||
}
|
||||
|
||||
} // namesapce BuildingViewer
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-08-15
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <string>
|
||||
#include "BgViewer/viewerCtrl/viewerinterface.h"
|
||||
#include "bdv_helper.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QVector3D>
|
||||
|
||||
#include "logger.h"
|
||||
#include <Common/buildingviewercommon_export.h>
|
||||
#include <BuildingViewer/share/exccommands.h>
|
||||
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
|
||||
#include <ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <LtsUtilsCore/qpoint3d.h>
|
||||
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class ViewerInterface;
|
||||
}
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
struct DeviceInfo
|
||||
{
|
||||
QString deviceName;
|
||||
int buildingId = 0;
|
||||
|
||||
DeviceInfo() = default;
|
||||
DeviceInfo(int _buildingId, const QString &_deviceName)
|
||||
: deviceName(_deviceName)
|
||||
, buildingId(_buildingId)
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Interface which provides methods respectively signals to communicate
|
||||
* with the BgViewer application which is started as a separate process.
|
||||
*/
|
||||
class BUILDINGVIEWERCOMMON_EXPORT CommunicationInterfaceInternal final : public QObject, public VCtrl::ViewerCallback
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CommunicationInterfaceInternal(VCtrl::ViewerInterface* pviewerInterface);
|
||||
|
||||
void playerCreate(int playerID, int partyID, const QString &strPathToSymbolFile,
|
||||
const LtsUtils::QPoint3D &pos, int buildingID , int roomNumber, Core::PositionReportingSource reportingSource);
|
||||
void playerPlace(int playerID, const LtsUtils::QPoint3D &pos,
|
||||
int buildingID, int roomNumber, Core::PositionReportingSource reportingSource);
|
||||
void playerDelete(int playerID);
|
||||
void setPlayerVisible(int playerID, bool bVisible);
|
||||
void playerClear();
|
||||
void playerUpdateSymbols();
|
||||
void playerUpdatePlayerSymbol(int playerID, const QString &strPathToSymbolFile);
|
||||
void playerHit(const int32_t id, int playerIdSrc, int playerIdDst,
|
||||
const LtsUtils::QPoint3D &posSrc, const LtsUtils::QPoint3D &posDst,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst, int lineType,
|
||||
int64_t time);
|
||||
void buildingHit(const int32_t id, int buildingId, int damagePercent, const QMap<int, int> &mapRoomDestructions);
|
||||
void roomHit(const int32_t id, int playerIdSrc, int buildingId, int roomNumber, const LtsUtils::QPoint3D &posSrc, int lineType, int64_t time);
|
||||
void removeRoomHit(const int32_t id);
|
||||
|
||||
void setTeamConfiguration(const QMap<qint32, ParticipantManagement::Party>& parties);
|
||||
|
||||
void systemSetSimulationTime(qint64 time);
|
||||
void setSimuationPace(double pace);
|
||||
void systemDisconnect();
|
||||
void systemSetPaused(bool bPaused);
|
||||
void systemSetMountingPoint(const InfrastructureManagement::MountingPoint &data, const QString &filename, bool show);
|
||||
|
||||
void excConnect(const std::vector<std::string> &paths, const QString &strXMLFile = QString());
|
||||
void excDeleteBuildingList();
|
||||
void excSetHitlineDuration(uint32_t duration_s);
|
||||
void excUseExactPositioning(bool useExactPositioning);
|
||||
void excOpenView(const std::vector<std::string> &bldIds);
|
||||
void excCloseView(const std::vector<std::string> &bldIds);
|
||||
void excCloseAllViews();
|
||||
void excStartRecording(const QString &strPathOutputFolder, const QString &buildingId = QStringLiteral("all"),
|
||||
int w = 800, int h = 600, int framerate = 20, int quality = 100);
|
||||
void excStopRecording(const QString &buildingId = QStringLiteral("all"));
|
||||
void excHighlightView(const QString &buildingId);
|
||||
void excSetGlobalTransparency(double transparency);
|
||||
void excSetGlobalViewMode(bool useOrtho);
|
||||
void excSetGlobalDotsMode(bool useDots);
|
||||
void excGetBuildingList();
|
||||
void excRestoreViewState(const QJsonValue &val);
|
||||
void excGetViewState();
|
||||
void excSetRoomDisplayName(const QString &strFeatureID, const QString &strRoomName, const QString &strRoomDisplayName);
|
||||
void excSetBuildingDisplayName(const QString &buildingId, const QString &strBuildingDisplayName);
|
||||
void extSetMountingPointAsset(const QString &strFeatureID, const QString &strMountingPointId, const QVector3D &position, BuildingViewer::AssetTypes assetType);
|
||||
void extHideMountingPointAsset(const QString &strMountingPointId);
|
||||
|
||||
// VCtrl::ViewerCallback interface
|
||||
void SystemReady() override;
|
||||
void TransformChanged(const std::string &id, const VCtrl::Vec3d &pos, const VCtrl::Quat &attitude) override;
|
||||
void NavMeshGroupChanged(const std::string &id, const std::string &grpname) override;
|
||||
void PlayerPicked(const std::string &strId) override;
|
||||
void DisplayNamePicked(const std::string &buildingid, const std::string &roomname) override;
|
||||
void ViewCreated(unsigned int contextId, VCtrl::ViewMode viewmode) override;
|
||||
void ViewModeChanged(unsigned int contextId, VCtrl::ViewMode viewmode) override;
|
||||
void ViewLineModeChanged(unsigned int contextId, bool line) override;
|
||||
void ViewNameModeChanged(unsigned int contextId, bool name) override;
|
||||
void ViewLockRotationChanged(unsigned int contextId, bool lock) override;
|
||||
void ViewTransparencyChanged() override;
|
||||
void PlayerDisplayModeChanged(unsigned int contextId, VCtrl::PlayerDisplayMode mode) override;
|
||||
void ViewClosed(unsigned int contextId) override;
|
||||
void HandleViewerEvent(BuildingViewer::BgViewerEvents event,
|
||||
const std::vector<std::string> &args) override;
|
||||
void ViewZoomChanged(const std::string &buildingId, double top, double left, double bottom, double right) override;
|
||||
void LogMessage(Severity &severity, const std::string &filename, const std::string &methodname,
|
||||
int linenumber, const std::string &msg) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void signalBgViewerInitFinished();
|
||||
void signalReceivedBuildingList(const QVector<BuildingTuple> &states);
|
||||
void signalReceivedViewState(const QJsonValue &state);
|
||||
|
||||
void signalPlayerPicked(int playerId);
|
||||
void signalAssetPicked(int structureElementId);
|
||||
void signalViewerEventWidgetClosed(const QString &featureID);
|
||||
void signalViewerEventWidgetMaximized(const QString &featureID);
|
||||
void signalViewerEventWidgetMinimized(const QString &featureID);
|
||||
void signalViewerEventWidgetFocused(const QString &featureID);
|
||||
void signalViewerEventButton();
|
||||
|
||||
void signalViewerEventRoomNameClicked(const QString &featureID, const QString &roomID);
|
||||
void signalViewerZoomChanged(const QString &featureId, double top, double left, double bottom, double right);
|
||||
|
||||
private:
|
||||
// Cameras, ...
|
||||
void clearCameras();
|
||||
QHash<QString, DeviceInfo> m_deviceMap;
|
||||
|
||||
// Party stuff
|
||||
struct BdvParty
|
||||
{
|
||||
QString name;
|
||||
VCtrl::Color color;
|
||||
int id = 0;
|
||||
};
|
||||
QHash<int, BdvParty> m_teamMap;
|
||||
|
||||
// Player stuff
|
||||
QHash<int, int> m_player2TeamMap; // playerID to teamID
|
||||
QHash<int, std::string> m_playerId2String; // playerId <-> uniqueId
|
||||
QMap<std::string, int> m_string2PlayerId; // uniqueId <-> playerId
|
||||
|
||||
VCtrl::ViewerInterface *m_pviewerInterface = nullptr;
|
||||
bool m_useExactPositioning = true;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
}
|
||||
+442
@@ -0,0 +1,442 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-08-14
|
||||
*/
|
||||
|
||||
#include "bdv_controller.h"
|
||||
#include "bdv_dds_controller.h"
|
||||
#include "bdv_bgviewer_widget_container.h"
|
||||
|
||||
#include <LtsAppManager/lts_app_manager.h>
|
||||
#include <LtsPluginManager/lts_plugin_manager.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <Common/bdv_communication_interface_internal.h>
|
||||
#include <Common/bdv_plugin_provider.h>
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
static int argc_dummy = 1;
|
||||
static char *argv_dummy[] = { (char*)"Dummy" };
|
||||
|
||||
BgViewerController::BgViewerController(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_mainloop(argc_dummy, argv_dummy, nullptr)
|
||||
, m_widgetStolen(false)
|
||||
, m_comIfc(nullptr)
|
||||
, m_pBgViewerDDSController(nullptr)
|
||||
, m_bgvApp(nullptr)
|
||||
, m_tickTimer(new QTimer(this))
|
||||
, m_logger(getLogger("BgViewerControllerSingleton"))
|
||||
{
|
||||
m_tickTimer->setInterval(1000 / 25); // 25fps
|
||||
connect(m_tickTimer, &QTimer::timeout, this, [this]() { m_mainloop.tick(); });
|
||||
|
||||
m_mainloop.getViewerInterface()->getMainWindow()->setMinimumSize(200, 200);
|
||||
|
||||
m_viewerInterface = m_mainloop.getViewerInterface();
|
||||
m_comIfc = new CommunicationInterfaceInternal(m_viewerInterface);
|
||||
m_viewerInterface->SetViewerCallback(m_comIfc);
|
||||
|
||||
m_pBgViewerDDSController = new BuildingViewerDdsController(m_comIfc, m_viewerInterface);
|
||||
|
||||
connect(m_pBgViewerDDSController, &BuildingViewerDdsController::signalDdsInitFinished, this, [this]() {
|
||||
m_initExerciseWasSuccessful = true;
|
||||
});
|
||||
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalBgViewerInitFinished,
|
||||
this, &BgViewerController::signalBgViewerInitFinished);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalReceivedBuildingList,
|
||||
this, &BgViewerController::signalReceivedBuildingList);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalReceivedViewState,
|
||||
this, &BgViewerController::signalReceivedViewState);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalPlayerPicked,
|
||||
this, &BgViewerController::signalPlayerPicked);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalAssetPicked,
|
||||
this, &BgViewerController::signalAssetPicked);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventWidgetClosed,
|
||||
this, &BgViewerController::signalViewerEventWidgetClosed);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventWidgetMaximized,
|
||||
this, &BgViewerController::signalViewerEventWidgetMaximized);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventWidgetMinimized,
|
||||
this, &BgViewerController::signalViewerEventWidgetMinimized);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventWidgetFocused,
|
||||
this, &BgViewerController::signalViewerEventWidgetFocused);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventRoomNameClicked,
|
||||
this, &BgViewerController::signalViewerEventRoomNameClicked);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerZoomChanged,
|
||||
this, &BgViewerController::signalViewerZoomChanged);
|
||||
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventButton,
|
||||
this, &BgViewerController::signalViewerEventButton);
|
||||
|
||||
}
|
||||
|
||||
|
||||
BgViewerController::~BgViewerController()
|
||||
{
|
||||
delete m_tickTimer;
|
||||
|
||||
if (m_bgvApp != nullptr)
|
||||
{
|
||||
m_bgvApp->disconnect();
|
||||
delete m_bgvApp;
|
||||
}
|
||||
|
||||
delete m_pBgViewerDDSController;
|
||||
delete m_comIfc;
|
||||
|
||||
m_bgvApp = nullptr;
|
||||
m_comIfc = nullptr;
|
||||
m_pBgViewerDDSController = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerController::excConnect(const std::vector<std::string> &paths, const QString &strXMLFile)
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excConnect(paths, strXMLFile);
|
||||
}
|
||||
|
||||
void BgViewerController::excGetBuildingList()
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excGetBuildingList();
|
||||
}
|
||||
|
||||
void BgViewerController::excGetViewState()
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excGetViewState();
|
||||
}
|
||||
|
||||
void BgViewerController::excHighlightView(const QString &strFeatureID)
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excHighlightView(strFeatureID);
|
||||
}
|
||||
|
||||
void BgViewerController::excRestoreViewState(const QJsonValue &state)
|
||||
{
|
||||
if (m_comIfc)
|
||||
{
|
||||
m_comIfc->excRestoreViewState(state);
|
||||
m_comIfc->excGetBuildingList();
|
||||
}
|
||||
}
|
||||
|
||||
void BgViewerController::excSetGlobalDotsMode(bool useDots)
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excSetGlobalDotsMode(useDots);
|
||||
}
|
||||
|
||||
void BgViewerController::excSetGlobalTransparency(double transparency)
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excSetGlobalTransparency(transparency);
|
||||
}
|
||||
|
||||
void BgViewerController::excSetGlobalViewMode(bool useOrtho)
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excSetGlobalViewMode(useOrtho);
|
||||
}
|
||||
|
||||
void BgViewerController::excSetHitlineDuration(uint32_t duration_s)
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excSetHitlineDuration(duration_s);
|
||||
}
|
||||
|
||||
void BgViewerController::excStartRecording(const QString &strPathOutputFolder,
|
||||
const QString &strFeatureID,
|
||||
int w, int h, int framerate, int quality)
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excStartRecording(strPathOutputFolder, strFeatureID, w, h, framerate, quality);
|
||||
}
|
||||
|
||||
void BgViewerController::excStopRecording(const QString &strFeatureID)
|
||||
{
|
||||
if (m_comIfc)
|
||||
m_comIfc->excStopRecording(strFeatureID);
|
||||
}
|
||||
|
||||
QString BgViewerController::buildingModelPath()
|
||||
{
|
||||
QVector<QString> directoriesToSearch = NGL::directories(NGL::FileType::ConfigFile);
|
||||
#ifndef WIN32
|
||||
directoriesToSearch += QStringLiteral("/opt");
|
||||
#endif
|
||||
|
||||
for (const QString &d : qAsConst(directoriesToSearch))
|
||||
{
|
||||
const QDir dir(d + QStringLiteral("/BuildingModels/StaticMeshes/"));
|
||||
if (dir.exists() && dir.isReadable())
|
||||
return dir.absolutePath();
|
||||
INFO_LOG(getLogger("BgViewerController")) << "Map path '" << dir.absolutePath() << "' either does not exist or is not readable - skipping";
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void BgViewerController::clearInterfaces(const LtsSession::DdsConnectionParams &conParams)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "BgViewerControllerSingleton::clearInterfaces()";
|
||||
if (m_pBgViewerDDSController && m_currentDdsConnParams == conParams)
|
||||
{
|
||||
m_pBgViewerDDSController->uninitialize();
|
||||
m_currentDdsConnParams = LtsSession::DdsConnectionParams();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerController::hideLiveVideo()
|
||||
{
|
||||
/* if (m_pBgViewerDDSController)
|
||||
if (m_pBgViewerDDSController->activeSession())
|
||||
if (m_pBgViewerDDSController->activeSession()->avmDataIfc())
|
||||
m_pBgViewerDDSController->activeSession()->avmDataIfc()->hideLiveVideo();
|
||||
*/
|
||||
// js ftw: m_pBgViewerDDSController?->activeSession()?->avmDataIfc()?->hideLiveVideo();
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerController::isBgViewerApplicationRunning() const
|
||||
{
|
||||
return (m_bgvApp != nullptr);
|
||||
}
|
||||
|
||||
|
||||
LtsSession::DdsConnectionParams BgViewerController::currentDdsConnParams() const
|
||||
{
|
||||
return m_currentDdsConnParams;
|
||||
}
|
||||
|
||||
|
||||
PluginProvider *BgViewerController::activeSession() const
|
||||
{
|
||||
return m_pBgViewerDDSController->activeSession();
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerController::init(PluginProvider *pSession, bool bStartRendering, const QString &modelPath)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "getDdsController init: " << pSession->toString();
|
||||
|
||||
if (m_currentDdsConnParams == pSession->connParams())
|
||||
{
|
||||
if (m_initExerciseWasSuccessful)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "BgViewerControllerSingleton::init Already initialized";
|
||||
slotLoadBuilding();
|
||||
|
||||
// Already initialized
|
||||
//emit signalExerciseInitializationComplete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
m_currentDdsConnParams = pSession->connParams();
|
||||
m_initExerciseWasSuccessful = false;
|
||||
if (!m_pBgViewerDDSController->init(m_bgViewerBaseLayoutWidget, modelPath, pSession))
|
||||
return false;
|
||||
if (bStartRendering)
|
||||
{
|
||||
m_bgvAppIsInitialized = true;
|
||||
m_tickTimer->start();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BgViewerController::forceInit(PluginProvider *pSession)
|
||||
{
|
||||
delete m_pBgViewerDDSController;
|
||||
m_pBgViewerDDSController = new BuildingViewerDdsController(m_comIfc, m_viewerInterface);
|
||||
|
||||
DEBUG_LOG(m_logger) << "FORCE INIT! with " << pSession;
|
||||
return (m_pBgViewerDDSController->init(m_bgViewerBaseLayoutWidget, buildingModelPath(), pSession));
|
||||
|
||||
}
|
||||
|
||||
void BgViewerController::showBgViewerInfoMessageBox()
|
||||
{
|
||||
static bool showMsgBox = true;
|
||||
|
||||
if (!showMsgBox)
|
||||
return;
|
||||
|
||||
QMessageBox msgbox;
|
||||
msgbox.setText(tr("BuildingViewer is currently used by another application.\nPlease close the corresponding application."));
|
||||
msgbox.setIcon(QMessageBox::Information);
|
||||
msgbox.addButton(QMessageBox::Ok);
|
||||
|
||||
QCheckBox *cb = new QCheckBox(tr("Do not show this message again."));
|
||||
msgbox.setCheckBox(cb);
|
||||
|
||||
connect(cb, &QCheckBox::stateChanged, [](int state) {
|
||||
showMsgBox = state != Qt::Checked;
|
||||
});
|
||||
|
||||
msgbox.exec();
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerController::startBgViewerAppInSession(PluginProvider* pStartingSession)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << std::hex << this << " startBgViewerAppInSession " << (m_currentDdsConnParams == pStartingSession->connParams());
|
||||
|
||||
if (m_bgvApp && (m_currentDdsConnParams == pStartingSession->connParams()))
|
||||
{
|
||||
INFO_LOG(m_logger) << std::hex << this << " BuildingViewer already opened. Doing nothing...";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Widget is stolen but BgViewer App is not running -> Do not start App
|
||||
if (!m_bgvApp && m_widgetStolen)
|
||||
{
|
||||
showBgViewerInfoMessageBox();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_bgvApp)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << std::hex << this << " Releasing m_bgvApp";
|
||||
delete m_bgvApp;
|
||||
m_bgvApp = nullptr;
|
||||
|
||||
clearInterfaces(m_currentDdsConnParams);
|
||||
m_comIfc->excCloseAllViews();
|
||||
}
|
||||
|
||||
m_bgvAppIsInitialized = false;
|
||||
m_bgvApp = LtsAppManager::LtsAppManager::getInstance()->createApp(LtsAppDescriptor::App::BuildingViewer, pStartingSession->connParams());
|
||||
if (!m_bgvApp || !m_bgvApp->sessions().size())
|
||||
{
|
||||
ERROR_LOG(m_logger) << std::hex << this << " m_bgvApp is nullptr or has no associated session!";
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(m_bgvApp, &LtsPluginManager::LtsPluginManager::signalInitializationFinished,
|
||||
this, [this, pStartingSession]()
|
||||
{
|
||||
m_tickTimer->start();
|
||||
m_bgvAppIsInitialized = true;
|
||||
|
||||
QWidget *w = nullptr;
|
||||
if (m_bgvApp)
|
||||
{
|
||||
LtsSession::LtsSession *session = m_bgvApp->getSession(pStartingSession->connParams().partitionType, pStartingSession->connParams().partitionId);
|
||||
w = session->baseLayoutWidget();
|
||||
}
|
||||
m_bgViewerBaseLayoutWidget = w;
|
||||
|
||||
slotLoadBuilding();
|
||||
emit bgvAppIsInitialized();
|
||||
});
|
||||
|
||||
connect(m_bgvApp, &LtsPluginManager::LtsPluginManager::destroyed,
|
||||
this, [this]()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << std::hex << this << " LtsPluginManager destroyed m_bgvApp";
|
||||
m_tickTimer->stop();
|
||||
clearInterfaces(m_currentDdsConnParams);
|
||||
m_comIfc->excCloseAllViews();
|
||||
m_bgvAppIsInitialized = false;
|
||||
m_bgvApp = nullptr;
|
||||
m_bgViewerBaseLayoutWidget = nullptr;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QWidget *BgViewerController::getBgViewerWidget()
|
||||
{
|
||||
if (m_widgetStolen)
|
||||
{
|
||||
showBgViewerInfoMessageBox();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BgViewerWidgetContainer *pDummy = new BgViewerWidgetContainer(m_mainloop.getViewerInterface()->getMainWindow());
|
||||
|
||||
m_widgetStolen = true;
|
||||
connect(pDummy, &BgViewerWidgetContainer::signalWidgetReleased, this, &BgViewerController::slotWidgetReleased);
|
||||
return pDummy;
|
||||
}
|
||||
|
||||
void BgViewerController::slotWidgetReleased()
|
||||
{
|
||||
m_widgetStolen = false;
|
||||
}
|
||||
|
||||
void BgViewerController::openBuilding(const QString &strBuildingFeatureId)
|
||||
{
|
||||
m_buildingsToShow.push_back(strBuildingFeatureId.toStdString());
|
||||
slotLoadBuilding();
|
||||
}
|
||||
|
||||
void BgViewerController::closeBuilding(const QString &strBuildingFeatureId)
|
||||
{
|
||||
if (!strBuildingFeatureId.isEmpty())
|
||||
{
|
||||
const std::string s = strBuildingFeatureId.toStdString();
|
||||
m_buildingsToShow.erase(std::remove_if(m_buildingsToShow.begin(), m_buildingsToShow.end(),
|
||||
[s](const std::string &str) { return s == str;}), m_buildingsToShow.end());
|
||||
}
|
||||
else
|
||||
m_buildingsToShow.clear();
|
||||
|
||||
if (m_comIfc)
|
||||
{
|
||||
if (strBuildingFeatureId.isEmpty())
|
||||
m_comIfc->excCloseAllViews();
|
||||
else
|
||||
m_comIfc->excCloseView({strBuildingFeatureId.toStdString()});
|
||||
m_comIfc->excGetBuildingList();
|
||||
}
|
||||
}
|
||||
|
||||
void BgViewerController::updatePlayerSymbols(int size)
|
||||
{
|
||||
m_pBgViewerDDSController->updatePlayerSymbols(size);
|
||||
}
|
||||
|
||||
void BgViewerController::closeAll()
|
||||
{
|
||||
m_bgvApp->deleteLater();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called each time 'signalInitializationComplete' is emitted. If the user started the BuildingViewer-App
|
||||
* with specifying a building (see 'showBgViewerApplication'), e.g. by starting it through clicking on a building on the situation map,
|
||||
* this slot will load the specified building. Otherwise, nothing will happen.
|
||||
*/
|
||||
void BgViewerController::slotLoadBuilding()
|
||||
{
|
||||
if (!m_bgvAppIsInitialized)
|
||||
return;
|
||||
m_comIfc->excOpenView(m_buildingsToShow);
|
||||
m_comIfc->excGetBuildingList();
|
||||
m_buildingsToShow.clear();
|
||||
}
|
||||
|
||||
void BgViewerController::slotStartRecording(const QString &strFolderPath, const QJsonValue &state)
|
||||
{
|
||||
excRestoreViewState(state);
|
||||
excStartRecording(strFolderPath, QStringLiteral("all"), 800, 600, 15, 40);
|
||||
}
|
||||
|
||||
void BgViewerController::slotStopRecording()
|
||||
{
|
||||
excStopRecording();
|
||||
}
|
||||
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* DDS IFC to BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-08-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QString>
|
||||
|
||||
#include <Common/buildingviewercommon_export.h>
|
||||
#include <BuildingViewer/share/exccommands.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsSession/lts_session_data_dds.h>
|
||||
#include <memory>
|
||||
#include "logger.h"
|
||||
#include "bdv_helper.h"
|
||||
#include "BgViewer/viewerCtrl/mainloop.h"
|
||||
|
||||
class QWidget;
|
||||
namespace LtsPluginManager
|
||||
{
|
||||
class LtsPluginManager;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialization sequence:
|
||||
*
|
||||
* CommunicationInterface:
|
||||
* 1. BgViewer is started as an external application
|
||||
* 1.1 A network connection is established
|
||||
* 1.2 The BgViewer window is "stolen" by requesting the window id via network
|
||||
* 1.3 Signal 'signalBgViewerInitFinished' is emitted
|
||||
*
|
||||
* BuildingViewerDdsController:
|
||||
* 2. DdsController receives this signal and sets the current training area
|
||||
* 2.1 BgViewer respectively emits 'signalBgViewerInitFinished' when the BgViewer loaded all models
|
||||
* 2.2 Mounting points, teams, participants, etc. are transmitted to the BgViewer
|
||||
* 2.3 DdsController emits 'signalDdsInitFinished'
|
||||
*
|
||||
* Finally, the signal 'signalDdsInitFinished' may be used to start requests to the BgViewer, e.g., requesting the Building list.
|
||||
*/
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class CommunicationInterfaceInternal;
|
||||
class BuildingViewerDdsController;
|
||||
class PluginProvider;
|
||||
|
||||
class BUILDINGVIEWERCOMMON_EXPORT BgViewerController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BgViewerController(QObject *parent = nullptr);
|
||||
~BgViewerController();
|
||||
|
||||
void clearInterfaces(const LtsSession::DdsConnectionParams &conParams);
|
||||
|
||||
bool isBgViewerApplicationRunning() const;
|
||||
LtsSession::DdsConnectionParams currentDdsConnParams() const;
|
||||
|
||||
bool startBgViewerAppInSession(PluginProvider *pStartingSession);
|
||||
void openBuilding(const QString &strBuildingFeatureId);
|
||||
void closeBuilding(const QString &strBuildingFeatureId = QString()); // empty string = all
|
||||
bool forceInit(PluginProvider *pSession);
|
||||
void updatePlayerSymbols(int size);
|
||||
void closeAll();
|
||||
// Also for/by SkriptPlayer
|
||||
QWidget *getBgViewerWidget();
|
||||
bool init(PluginProvider *pSession, bool bStartRendering = false, const QString &modelPath = buildingModelPath());
|
||||
PluginProvider *activeSession() const;
|
||||
|
||||
// from communication interface
|
||||
void excConnect(const std::vector<std::string> &paths, const QString &strXMLFile = QString());
|
||||
void excGetBuildingList();
|
||||
void excGetViewState();
|
||||
void excHighlightView(const QString &strFeatureID);
|
||||
void excRestoreViewState(const QJsonValue &state);
|
||||
void excSetGlobalDotsMode(bool useDots);
|
||||
void excSetGlobalTransparency(double transparency);
|
||||
void excSetGlobalViewMode(bool useOrtho);
|
||||
void excSetHitlineDuration(uint32_t duration_s);
|
||||
void excStartRecording(const QString &strPathOutputFolder,
|
||||
const QString &strFeatureID = QStringLiteral("all"),
|
||||
int w = 800, int h = 600,
|
||||
int framerate = 20, int quality = 100);
|
||||
void excStopRecording(const QString &strFeatureID = QStringLiteral("all"));
|
||||
|
||||
static QString buildingModelPath();
|
||||
|
||||
LtsPluginManager::LtsPluginManager *app() { return m_bgvApp; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void bgvAppIsInitialized();
|
||||
|
||||
// from communication interface
|
||||
void signalBgViewerInitFinished();
|
||||
void signalReceivedBuildingList(const QVector<BuildingTuple> &list);
|
||||
void signalReceivedViewState(const QJsonValue &state);
|
||||
|
||||
void signalViewerEventButton();
|
||||
void signalPlayerPicked(int playerId);
|
||||
void signalAssetPicked(int structureElementId);
|
||||
void signalViewerEventWidgetClosed(const QString &featureID);
|
||||
void signalViewerEventWidgetMaximized(const QString &featureID);
|
||||
void signalViewerEventWidgetMinimized(const QString &featureID);
|
||||
void signalViewerEventWidgetFocused(const QString &featureID);
|
||||
void signalViewerEventRoomNameClicked(const QString &featureID, const QString &roomID);
|
||||
void signalViewerZoomChanged(const QString &featureId, double top, double left, double bottom, double right);
|
||||
|
||||
public slots:
|
||||
void slotStartRecording(const QString &strFolderPath, const QJsonValue &state);
|
||||
void slotStopRecording();
|
||||
void hideLiveVideo();
|
||||
|
||||
private slots:
|
||||
void slotLoadBuilding();
|
||||
void slotWidgetReleased();
|
||||
|
||||
private:
|
||||
void showBgViewerInfoMessageBox();
|
||||
|
||||
private:
|
||||
VCtrl::MainLoop m_mainloop;
|
||||
bool m_widgetStolen;
|
||||
|
||||
std::vector<std::string> m_buildingsToShow;
|
||||
CommunicationInterfaceInternal *m_comIfc{nullptr};
|
||||
VCtrl::ViewerInterface *m_viewerInterface{nullptr};
|
||||
BuildingViewerDdsController *m_pBgViewerDDSController;
|
||||
|
||||
bool m_initExerciseWasSuccessful{false};
|
||||
LtsSession::DdsConnectionParams m_currentDdsConnParams;
|
||||
LtsPluginManager::LtsPluginManager *m_bgvApp;
|
||||
|
||||
bool m_bgvAppIsInitialized{false};
|
||||
|
||||
QTimer *m_tickTimer{nullptr};
|
||||
QWidget *m_bgViewerBaseLayoutWidget{nullptr};
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
}
|
||||
|
||||
+1727
File diff suppressed because it is too large.
Load diff
+1472
File diff suppressed because it is too large.
Load diff
+185
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* DDS IFC to BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-08-17
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QHash>
|
||||
#include <QVector>
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <Plugins/AdvancedSymbology/asb_data_plugin_interface.h>
|
||||
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
|
||||
#include <Plugins/AudioVideoManagement/avm_data_plugin_interface.h>
|
||||
#include <Plugins/Buildings/bld_data_plugin_interface.h>
|
||||
#include <Plugins/SituationReplay/srp_data_plugin_interface.h>
|
||||
#include <Plugins/Buildings/bld_info_gui_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <Plugins/ProjectDataManagement/pdm_data_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_participant_info_gui_plugin_interface.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <Plugins/SituationReplay/srp_data_plugin_interface.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <LtsUtilsCore/qpoint3d.h>
|
||||
#include <Common/buildingviewercommon_export.h>
|
||||
#include <BuildingViewer/share/exccommands.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <viewerinterface.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class CommunicationInterfaceInternal;
|
||||
class PluginProvider;
|
||||
|
||||
class BuildingViewerDdsController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BuildingViewerDdsController(CommunicationInterfaceInternal *connection,
|
||||
VCtrl::ViewerInterface* viewerInterface);
|
||||
~BuildingViewerDdsController();
|
||||
bool init(QWidget *irreplacableWidget, const QString &modelPath, PluginProvider *session);
|
||||
void uninitialize();
|
||||
|
||||
void updatePlayerSymbols(const int sizeL, const int forParty = -1);
|
||||
|
||||
void clearAssets();
|
||||
PluginProvider *activeSession() const { return m_session; }
|
||||
|
||||
signals:
|
||||
void signalDdsInitFinished();
|
||||
private:
|
||||
void setCurrentTrainingAreaMap(const QString &modelPath);
|
||||
private slots:
|
||||
void onPartyChanged(const ParticipantManagement::Party &party, DataModification modType);
|
||||
void onBgViewerInitFinished();
|
||||
void onFireEventFlashTimer();
|
||||
void onSynchronizeSimulationTime();
|
||||
void onBoobyTrapChanged(const AreaEffectSimulation::BoobyTrap &boobyTrap, DataModification modType);
|
||||
void onParticipantChanged(const ParticipantManagement::Participant &participant, DataModification modType);
|
||||
void onDynParticipantChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType);
|
||||
void onPositionChanged(const ParticipantManagement::ParticipantPosition &position, DataModification modType);
|
||||
void onHitLineInfoChanged(const ParticipantManagement::HitLineInfo &hli, DataModification modType);
|
||||
void onParticipantGearEventChanged(const ParticipantManagement::ParticipantGearEvent &data, DataModification modType);
|
||||
|
||||
void onPlayerPicked(int playerId);
|
||||
void onAssetPicked(int structureElementId);
|
||||
void onMountingPointChanged(const InfrastructureManagement::MountingPoint &data, DataModification modType);
|
||||
void onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType);
|
||||
void onCleanupBuildingHitlines();
|
||||
void onBuildingHitLineInfoChanged(const Buildings::BuildingHitLineInfo &hli, DataModification modType);
|
||||
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType);
|
||||
|
||||
private:
|
||||
QPointF toRelativePosition(const Core::GeoPosition &geoPos) const;
|
||||
LtsUtils::QPoint3D toRelative3D(const Core::GeoPosition &geoPos) const;
|
||||
bool clear();
|
||||
bool syncTeams();
|
||||
bool setPaused(bool bPaused);
|
||||
bool isOutdatedPosition(qint64 sampleTime) const;
|
||||
inline bool isOutdatedPosition(const ParticipantManagement::ParticipantPosition &position) const
|
||||
{
|
||||
return position.participantId() <= 0 || isOutdatedPosition(position.sampleTime());
|
||||
}
|
||||
|
||||
bool calcBaseCoordinate(const QMap<qint32, InfrastructureManagement::MainStructureElement> &mseMap);
|
||||
void sendAssets();
|
||||
void handleMountingPoint(const InfrastructureManagement::MountingPoint &mp, DataModification modType);
|
||||
void onReplayChanged(const SituationReplay::SitReplay &srp, DataModification modType);
|
||||
void effectGenerationUnitPicked(int structureElementId);
|
||||
QHash<int, BuildingViewer::AssetTypes> m_mountingPointId2AssetType;
|
||||
QHash<int, QString> m_knownAssetsInBgViewer;
|
||||
|
||||
void createBoobyTraps();
|
||||
void createParticipants();
|
||||
bool isValidParticipant(const ParticipantManagement::Participant &participant) const;
|
||||
void createParticipant(const ParticipantManagement::Participant &participant, const ParticipantManagement::ParticipantPosition &position, int sizeL);
|
||||
void createBoobyTrap(const AreaEffectSimulation::BoobyTrap &trap, int sizeL);
|
||||
void deleteParticipant(int participantId);
|
||||
void updateBuildingRoomNames(const InfrastructureManagement::MainStructureElement& building);
|
||||
bool writeBuildingDataToXML(const QString &modelPath);
|
||||
QString getBuildingConfigurationXml() const;
|
||||
|
||||
static QString buildPlayerSymbolFilePath(int playerID, int postfix = 0);
|
||||
|
||||
struct SymbolInfo
|
||||
{
|
||||
QString strPathToSymbolFile;
|
||||
QColor color;
|
||||
int participantId = -1;
|
||||
bool useThisSymbolNow = false;
|
||||
};
|
||||
|
||||
|
||||
QHash<int, qint64> m_participantGearEvents; // <playerId, sampleTime>
|
||||
QHash<int, qint64> m_lastPositionTime; // <playerId, sampleTime>
|
||||
struct BuildingHit
|
||||
{
|
||||
int32_t id = 0;
|
||||
int64_t sampleTime = 0;
|
||||
int originatorParticipantId = 0;
|
||||
int chargeTypeId = 0;
|
||||
};
|
||||
QHash<int, QVector<BuildingHit>> m_buildingHits;
|
||||
QVector<int> m_knownBuildings;
|
||||
inline bool isBuildingKnown(int id) const
|
||||
{
|
||||
return std::find(m_knownBuildings.cbegin(), m_knownBuildings.cend(), id) != m_knownBuildings.cend();
|
||||
}
|
||||
|
||||
const int cColorSymbolId = 0;
|
||||
const QVector<QColor> m_vecFlashColors = {QColor(), Qt::white, Qt::gray}; // First color is invalid -> actual party color will be used
|
||||
void createPlayerSymbols(const ParticipantManagement::Participant &participant, const int sizeL);
|
||||
void createSymbolResultWatcher(const ParticipantManagement::Participant &participant, const SymbolInfo &symbolInfo, const int sizeL);
|
||||
QHash<AdvancedSymbology::SymbolResultWatcher *, SymbolInfo> m_mapActiveSymbolResultWatcher; // ResultWatcher address -> Player id to update symbol for
|
||||
void reCheckHitLine();
|
||||
QString getSessionInfo() const;
|
||||
PluginProvider *m_session = nullptr;
|
||||
int m_exerciseId = -1;
|
||||
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> m_avmIfc;
|
||||
std::shared_ptr<AdvancedSymbology::ForeignDataInterface> m_asbIfc;
|
||||
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> m_aesDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_pdmDtc;
|
||||
std::shared_ptr<ParticipantManagement::ForeignParticipantInfoGuiInterface> m_ppmGuiIfc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_ismIfc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
std::shared_ptr<SituationReplay::Interface::Dtc> m_srpDtc;
|
||||
std::shared_ptr<Buildings::ForeignInfoGuiInterface> m_blgGuiIfc;
|
||||
|
||||
void stopAndClearTimer();
|
||||
QTimer *m_pSimTimeSyncTimer = nullptr;
|
||||
QTimer *m_pFireEventFlashTimer = nullptr;
|
||||
QTimer *m_pBuildingHitlineCleanupTimer = nullptr;
|
||||
bool m_ddsInitFinished = false;
|
||||
int m_dtc_timeout_ms = 10000;
|
||||
int m_hitlineDuration_ms = 10 * 1000;
|
||||
/*
|
||||
* Updating the simulation time causes the BgViewer to freeze for short moments from time to time.
|
||||
* E.g., 1000ms is a bad value. We stay with 10 seconds for now.
|
||||
*/
|
||||
int m_bgviewer_simSyncTimeInterval_ms = 3000; //10000;
|
||||
|
||||
QHash<int, QHash<int, int>> m_roomId2RoomNumber; // QHash<buildingId, QHash<roomId, roomNumber>> // roomNumber of xmlFile
|
||||
CommunicationInterfaceInternal *m_connection{nullptr};
|
||||
VCtrl::ViewerInterface* m_viewerInterface{nullptr};
|
||||
QTimer *m_reCheckTimer{nullptr};
|
||||
LtsCoordTrans::UtmCoordinate m_baseCoordinate;
|
||||
QHash < int32_t, double > m_buildingHeight; // Key = BuildingId, Value z-value from geoPosition of the building
|
||||
QWidget *m_irreplacableWidget {nullptr};
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} //namespace BuildingViewer
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-09-22
|
||||
*/
|
||||
|
||||
#include "bdv_helper.h"
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
QString gStrFeatureIdPrefix = QStringLiteral("House_");
|
||||
|
||||
/*
|
||||
* Converts a given building id (as used within the database) to the featureId
|
||||
* format which is internally used by the BuildingViewer
|
||||
*/
|
||||
QString databaseId2FeatureId(int32_t buildingDatabaseId)
|
||||
{
|
||||
if (buildingDatabaseId <= 0)
|
||||
return QString();
|
||||
return gStrFeatureIdPrefix + QString::number(buildingDatabaseId);
|
||||
}
|
||||
|
||||
|
||||
int32_t featureId2DatabaseId(const QString &strFeatureId)
|
||||
{
|
||||
if (!strFeatureId.startsWith(gStrFeatureIdPrefix))
|
||||
return -1;
|
||||
bool isOk = false;
|
||||
int32_t buildingDatabaseId = strFeatureId.midRef(gStrFeatureIdPrefix.size()).toInt(&isOk);
|
||||
return isOk ? buildingDatabaseId : -1;
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-09-22
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
#include <LtsUtilsCore/qpoint3d.h>
|
||||
#include <Common/buildingviewercommon_export.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
struct BuildingTuple
|
||||
{
|
||||
QString buildingId;
|
||||
QString description;
|
||||
int entityId = 0;
|
||||
bool isShown = false;
|
||||
};
|
||||
|
||||
// merge with BuildingTuple?
|
||||
struct BuildingInfo
|
||||
{
|
||||
QString name;
|
||||
LtsUtils::QPoint3D position;
|
||||
double angleDegree = 0;
|
||||
int id = 0;
|
||||
|
||||
bool operator==(const BuildingInfo &o) const
|
||||
{
|
||||
return id == o.id; // id is the key so this is enough
|
||||
}
|
||||
|
||||
static BuildingInfo fromJson(const QJsonObject &obj)
|
||||
{
|
||||
BuildingInfo ret;
|
||||
ret.name = obj[QStringLiteral("name")].toString();
|
||||
ret.position.rx() = obj[QStringLiteral("positionX")].toDouble();
|
||||
ret.position.ry() = obj[QStringLiteral("positionY")].toDouble();
|
||||
ret.position.rz() = obj[QStringLiteral("positionZ")].toDouble();
|
||||
ret.angleDegree = obj[QStringLiteral("angleDegree")].toDouble();
|
||||
ret.id = obj[QStringLiteral("id")].toInt();
|
||||
return ret;
|
||||
}
|
||||
QJsonObject toJson() const
|
||||
{
|
||||
return {
|
||||
{QStringLiteral("name"), name},
|
||||
{QStringLiteral("positionX"), position.x()},
|
||||
{QStringLiteral("positionY"), position.y()},
|
||||
{QStringLiteral("positionZ"), position.z()},
|
||||
{QStringLiteral("angleDegree"), angleDegree},
|
||||
{QStringLiteral("id"), id},
|
||||
};
|
||||
}
|
||||
bool isValid() const { return id > 0; }
|
||||
};
|
||||
|
||||
|
||||
QString BUILDINGVIEWERCOMMON_EXPORT databaseId2FeatureId(int32_t buildingDatabaseId);
|
||||
int32_t BUILDINGVIEWERCOMMON_EXPORT featureId2DatabaseId(const QString& strFeatureId);
|
||||
}
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Interface to provide access to Plugins needed by buildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <QObject>
|
||||
#include <Common/buildingviewercommon_export.h>
|
||||
|
||||
namespace AdvancedSymbology
|
||||
{
|
||||
class ForeignDataInterface;
|
||||
}
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
class DataInterface;
|
||||
using ForeignDataInterface = DataInterface;
|
||||
}
|
||||
|
||||
namespace Buildings
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
class ForeignInfoGuiInterface;
|
||||
}
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class ForeignDataInterface;
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
namespace AreaEffectSimulation
|
||||
{
|
||||
class ForeignDataInterface;
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
namespace SituationReplay
|
||||
{
|
||||
class ForeignDataInterface;
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
struct DdsConnectionParams;
|
||||
}
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
class ForeignParticipantInfoGuiInterface;
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProjectDataManagement
|
||||
{
|
||||
class ForeignDataInterface;
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BUILDINGVIEWERCOMMON_EXPORT PluginProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QObject::QObject;
|
||||
|
||||
virtual QString toString() const = 0;
|
||||
|
||||
virtual int exerciseId() const = 0;
|
||||
virtual qint64 partitionTime() const = 0;
|
||||
virtual bool isReplayPartition() const = 0;
|
||||
virtual bool isVisibleParty(int partyId) const = 0;
|
||||
virtual LtsSession::DdsConnectionParams connParams() const = 0;
|
||||
virtual quintptr adr() const { return 0; }
|
||||
|
||||
virtual std::shared_ptr<AdvancedSymbology::ForeignDataInterface> asbIfc() const = 0;
|
||||
virtual std::shared_ptr<AudioVideoManagement::ForeignDataInterface> avmDataIfc() const = 0; // optional
|
||||
virtual std::shared_ptr<Buildings::Interface::Dtc> bldDtc() const = 0;
|
||||
virtual std::shared_ptr<Buildings::ForeignInfoGuiInterface> bldInfoIfc() const = 0; // optional
|
||||
virtual std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc() const = 0;
|
||||
virtual std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismDataIfc() const = 0;
|
||||
virtual std::shared_ptr<AreaEffectSimulation::Interface::Dtc> aesDtc() const = 0; // optional
|
||||
virtual std::shared_ptr<ParticipantManagement::Interface::Dtc> ppmDtc() const = 0; // optional
|
||||
virtual std::shared_ptr<ProjectDataManagement::Interface::Dtc> pdmDtc() const = 0; // optional
|
||||
virtual std::shared_ptr<SituationReplay::Interface::Dtc> srpDtc() const = 0; // optional
|
||||
virtual std::shared_ptr<ParticipantManagement::ForeignParticipantInfoGuiInterface> ppmParticipantInfoIfc() const = 0; // optional
|
||||
|
||||
signals:
|
||||
void partitionTimeChanged(qint64 partitionTime);
|
||||
};
|
||||
} // namespace BuildingViewer
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building - logging facility
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "BDV.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-08-17
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
#include <Common/buildingviewercommon_export.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
typedef NGL::INGLLogger &LOGGER_T;
|
||||
|
||||
BUILDINGVIEWERCOMMON_EXPORT LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,16 @@
|
||||
uniform sampler2D diffuseTexture;
|
||||
varying vec3 vNormal;
|
||||
varying float vFog;
|
||||
varying vec4 vFrontColor;
|
||||
uniform vec4 wall_color;
|
||||
uniform vec4 room_color;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 diffuseColor = texture2D(diffuseTexture, gl_TexCoord[0].st);
|
||||
vec3 lightDir = vec3(normalize(gl_LightSource[0].position));
|
||||
vec4 ambient = gl_LightSource[0].ambient * diffuseColor;
|
||||
vec4 diffuse = gl_LightSource[0].diffuse * max(dot(vNormal,lightDir) * 0.5,0.0) * diffuseColor;
|
||||
gl_FragColor = (ambient + diffuse) * room_color;
|
||||
gl_FragColor.a = wall_color.a * room_color.a;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
varying vec3 vNormal;
|
||||
varying vec4 dest_color;
|
||||
varying vec4 vFrontColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = ftransform();
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_FrontColor = gl_Color;
|
||||
|
||||
vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec3 ecPosition3 = vec3(ecPosition) / ecPosition.w;
|
||||
gl_FogFragCoord = length(ecPosition3);
|
||||
vNormal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
vFrontColor = gl_FrontMaterial.specular;
|
||||
}
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
#include "bdv_building_edit.h"
|
||||
#include "bdv_edit_item.h"
|
||||
#include "ui_bdv_building_edit.h"
|
||||
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
#include <Buildings/bld_operator_rights.h>
|
||||
#include <Buildings/bld.hpp>
|
||||
#include <Buildings/bld_ftc.h>
|
||||
|
||||
#include <nglwidgets/ngltreeitem.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BuildingEdit::BuildingEdit(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_ui(new Ui::BuildingEdit)
|
||||
, m_logger(getLogger("BuildingViewer::BuildingEdit"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->hide();
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &BuildingEdit::slotEditItem);
|
||||
|
||||
bool userHasRightsToEdit = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BuildingViewerSettingsEdit);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setVisible(userHasRightsToEdit);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setVisible(userHasRightsToEdit);
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(false);
|
||||
|
||||
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
|
||||
const bool enableGuiDestroyRooms = ps->value(QStringLiteral("bld"),
|
||||
QStringLiteral("enableGuiDestroyRooms")).toBool();
|
||||
// Todo: Create Buttons for Destroying (and resetting?) rooms.
|
||||
auto btnDestroy = m_buttonBox->getButton(LtsWidgets::DialogButton::Add);
|
||||
btnDestroy->setText(tr("Destroy"));
|
||||
btnDestroy->setVisible(enableGuiDestroyRooms);
|
||||
// btnDestroy->setEnabled(false);
|
||||
connect(btnDestroy, &QPushButton::pressed, this, &BuildingEdit::onDestroyElement);
|
||||
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Building_Viewer-Building_List"));
|
||||
}
|
||||
|
||||
|
||||
BuildingEdit::~BuildingEdit()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Building Edit: %1").arg(m_buildingName));
|
||||
}
|
||||
|
||||
|
||||
bool BuildingEdit::init(int32_t buildingDatabaseId,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Ftc> &ismFtc,
|
||||
const std::shared_ptr<Buildings::Interface::Dtc> &bldDtc,
|
||||
const std::shared_ptr<Buildings::Interface::Ftc> &bldFtc)
|
||||
{
|
||||
if (m_ismDtc)
|
||||
return false;
|
||||
m_buildingDatabaseId = buildingDatabaseId;
|
||||
|
||||
m_ismDtc = ismDtc;
|
||||
m_ismFtc = ismFtc;
|
||||
m_bldDtc = bldDtc;
|
||||
m_bldFtc = bldFtc;
|
||||
|
||||
// Get building name to create a proper tab title
|
||||
InfrastructureManagement::MainStructureElement building = m_ismDtc->mainStructureElement(m_buildingDatabaseId);
|
||||
m_buildingId = building.id();
|
||||
|
||||
buildModel();
|
||||
m_buildingName = m_model->getBuildingName();
|
||||
|
||||
if (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BuildingViewerSettingsEdit))
|
||||
{
|
||||
connect(m_ui->treeViewEdit, &QTreeView::clicked, this, &BuildingEdit::slotTreeViewClicked);
|
||||
connect(m_ui->treeViewEdit, &QTreeView::doubleClicked, this, &BuildingEdit::slotDoubleClicked);
|
||||
connect(m_model, &BuildingEditModel::signalModelDataChanged, this, &BuildingEdit::slotChangesMade); // 'slotChangesMade' belongs to LtsWidgets::LtsDialog and enables apply button
|
||||
}
|
||||
|
||||
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
|
||||
this, &BuildingEdit::slotMainStructureElementChanged);
|
||||
|
||||
connect(m_bldDtc.get(), &Buildings::Interface::Dtc::buildingStateChanged,
|
||||
this, &BuildingEdit::slotBuildingStateChanged);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotTreeViewClicked()
|
||||
{
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(selectedIndexView().isValid());
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::buildModel()
|
||||
{
|
||||
m_model = new BuildingEditModel(this, m_ismDtc, m_bldDtc);
|
||||
|
||||
// SortFilterProxyModel:
|
||||
m_proxyModel = new BuildingEditProxyModel(this);
|
||||
m_proxyModel->setSourceModel(m_model);
|
||||
|
||||
// View treeView :
|
||||
m_ui->treeViewEdit->setModel(m_proxyModel);
|
||||
m_ui->treeViewEdit->expandAll();
|
||||
m_ui->treeViewEdit->sortByColumn(BuildingEditModel::Building, Qt::AscendingOrder);
|
||||
|
||||
// ContextMenu :
|
||||
m_ui->treeViewEdit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
m_model->init(m_buildingDatabaseId);
|
||||
m_ui->treeViewEdit->expandAll();
|
||||
m_ui->treeViewEdit->setColumnWidth(BuildingEditModel::Building, 230);
|
||||
#ifdef LTS_DEBUG
|
||||
m_ui->treeViewEdit->setColumnWidth(BuildingEditModel::Name, 150);
|
||||
m_ui->treeViewEdit->setColumnWidth(BuildingEditModel::MountingPointId, 120);
|
||||
m_ui->treeViewEdit->setColumnWidth(BuildingEditModel::StructureElementId, 80);
|
||||
#else
|
||||
m_ui->treeViewEdit->hideColumn(BuildingEditModel::Name);
|
||||
m_ui->treeViewEdit->hideColumn(BuildingEditModel::MountingPointId);
|
||||
m_ui->treeViewEdit->hideColumn(BuildingEditModel::StructureElementId);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
QModelIndex BuildingEdit::selectedIndexView() const
|
||||
{
|
||||
QItemSelectionModel *selectionModel = m_ui->treeViewEdit->selectionModel();
|
||||
QModelIndexList indexL = selectionModel->selectedRows(0);
|
||||
if (indexL.size() == 0)
|
||||
return QModelIndex();
|
||||
|
||||
return m_proxyModel->mapToSource(indexL.at(0));
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotEditItem()
|
||||
{
|
||||
QModelIndex selIndex = selectedIndexView();
|
||||
if (!selIndex.isValid())
|
||||
return;
|
||||
|
||||
BuildingViewer::TreeItem data = m_model->privateData(selIndex)->data().value<TreeItem>();
|
||||
|
||||
ParticipantEditItemWidget *newItemDlg = new ParticipantEditItemWidget(m_buildingName, data, this);
|
||||
newItemDlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
connect(newItemDlg, &ParticipantEditItemWidget::signalItemUpdated,
|
||||
m_model, &BuildingEditModel::slotUpdateRow);
|
||||
|
||||
newItemDlg->show();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Applies changes to the Dds structures. The actual updating of the room names and fortify factors
|
||||
* is done by the 'BuildingViewerDdsController' * which listen on changes related to the MainStructureElements
|
||||
* (See slot 'BuildingViewerDdsController::onMainStructureElementChanged')
|
||||
*/
|
||||
bool BuildingEdit::apply()
|
||||
{
|
||||
/*
|
||||
* FortifyFactor is set by using 'Building', room names are set by 'InfraStructureManagement'.
|
||||
* Hence, we have two reply handler. Both of them must return without a failure.
|
||||
*
|
||||
* However, it may be possible that only room names OR fortify factors have been changed.
|
||||
* E.g., if only fortify factors changed we set 'm_ismFtcReplySuccess' to true to indicate that
|
||||
* changing the room names was successful (-> nothing changed)
|
||||
*/
|
||||
const auto fortifyFactors = m_model->getRoomsWithChangedFortifyFactors();
|
||||
//m_blgFtcReplySuccess = fortifyFactors.size() ? false : true;
|
||||
|
||||
// Change fortify factors
|
||||
DEBUG_LOG(m_logger) << "fortifyFactors.size()=" << fortifyFactors.size();
|
||||
if (fortifyFactors.size())
|
||||
{
|
||||
m_requestHelper->addRequest([this, fortifyFactors]()
|
||||
{
|
||||
Buildings::SetFortifyFactorRequest fortifyRequest;
|
||||
fortifyRequest.buildingId(m_buildingDatabaseId);
|
||||
|
||||
// Get all factors for this building
|
||||
fortifyRequest.fortifyFactors().reserve(fortifyFactors.size());
|
||||
for (const auto &e : fortifyFactors)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "push_back= databaseId=" << e.structureElementId()
|
||||
<< " fortifyFactor=" << e.fortifyFactor();
|
||||
fortifyRequest.fortifyFactors().push_back(Buildings::FortifyFactor(e.structureElementId(), e.fortifyFactor()));
|
||||
}
|
||||
|
||||
return m_bldFtc->setFortifyFactorRequest(fortifyRequest, this);
|
||||
});
|
||||
}
|
||||
|
||||
// Change room display names
|
||||
const auto displayNames = m_model->getRoomsWithChangedDisplayNames();
|
||||
//m_ismFtcReplySuccess = mapDisplayNames.size() ? false : true;
|
||||
|
||||
|
||||
if (displayNames.size())
|
||||
{
|
||||
std::vector<InfrastructureManagement::StructureElement> vecModifiedRooms;
|
||||
vecModifiedRooms.reserve(displayNames.size());
|
||||
InfrastructureManagement::MainStructureElement building = m_ismDtc->mainStructureElement(m_buildingDatabaseId);
|
||||
|
||||
for (const auto &treeItem : displayNames)
|
||||
{
|
||||
// Get latest room data
|
||||
for (const auto &room : building.elements())
|
||||
{
|
||||
if (room.id() == treeItem.structureElementId())
|
||||
{
|
||||
auto copy = room;
|
||||
copy.displayName(treeItem.displayName().toStdString());
|
||||
vecModifiedRooms.push_back(copy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_requestHelper->addRequest([this, vecModifiedRooms]()
|
||||
{
|
||||
InfrastructureManagement::StructureElementModifyRequest request(m_buildingDatabaseId, vecModifiedRooms);
|
||||
return m_ismFtc->structureElementModifyRequest(request, this);
|
||||
});
|
||||
}
|
||||
return m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::selectRoomRow(int mountingPointId)
|
||||
{
|
||||
QModelIndex mIndex = m_model->modelIndexByStructureElementId(mountingPointId);
|
||||
m_ui->treeViewEdit->setCurrentIndex(mIndex); // Bug/ToDo: Row is not selected even though mIndex seems to be valid and correct
|
||||
m_ui->treeViewEdit->selectionModel()->setCurrentIndex(mIndex, QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::reinitModel()
|
||||
{
|
||||
m_model->init(m_buildingDatabaseId);
|
||||
m_ui->treeViewEdit->expandAll();
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotDoubleClicked(const QModelIndex &selIndex)
|
||||
{
|
||||
if (!selIndex.isValid())
|
||||
return;
|
||||
|
||||
slotEditItem();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Related to the usage of 'm_ismFtcReplySuccess' and 'm_blgFtcReplySuccess':
|
||||
* Changed received: -> Ftc was successful
|
||||
* Reply received: -> Ftc was successful
|
||||
*
|
||||
* However, a change might be received before receiving the reply and vice versa. Both are indicating success.
|
||||
* Hence, we simply set the appropriate variable to true in both cases.
|
||||
*/
|
||||
void BuildingEdit::slotMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType)
|
||||
{
|
||||
if(modType == DataModification::eRemoved)
|
||||
return;
|
||||
|
||||
if(mse.id() == m_buildingDatabaseId)
|
||||
{
|
||||
//m_ismFtcReplySuccess = true;
|
||||
slotHandleExternalDdsChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotBuildingStateChanged(const Buildings::BuildingState &state, DataModification modType)
|
||||
{
|
||||
if(modType == DataModification::eRemoved)
|
||||
return;
|
||||
|
||||
if(state.id() == m_buildingDatabaseId)
|
||||
{
|
||||
//m_blgFtcReplySuccess = true;
|
||||
slotHandleExternalDdsChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotHandleExternalDdsChange()
|
||||
{
|
||||
reinitModel();
|
||||
}
|
||||
|
||||
bool BuildingEdit::sendBuildingStateRequest(ProjectDataManagement::VulnerabilityState state, std::vector<int32_t> structureElementIds)
|
||||
{
|
||||
// aktuellen state aus Cbx ermitteln und LTS-SetBuildingState aufrufen
|
||||
m_requestHelper->addRequest([this, state, structureElementIds]()
|
||||
{
|
||||
Buildings::Building building;
|
||||
std::vector< Buildings::Building > buildings;
|
||||
buildings.resize(1);
|
||||
Buildings::SetBuildingStatesRequest requestData;
|
||||
//requestData.buildingId(m_buildingId);
|
||||
building.buildingId(m_buildingId);
|
||||
building.roomIds().set(structureElementIds);
|
||||
buildings[0] = building;
|
||||
requestData.buildings(buildings);
|
||||
requestData.vulnerabilityState(state);
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << "currentData: " << state;
|
||||
|
||||
return m_bldFtc->setBuildingStatesRequest(requestData, this);
|
||||
});
|
||||
|
||||
return m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
void BuildingEdit::onDestroyElement()
|
||||
{
|
||||
QModelIndex selIndex = selectedIndexView();
|
||||
if (!selIndex.isValid())
|
||||
return;
|
||||
|
||||
std::vector<int32_t> structureElementIds;
|
||||
getStructureElementIds(m_model->privateData(selIndex), structureElementIds);
|
||||
|
||||
sendBuildingStateRequest(ProjectDataManagement::VulnerabilityState_def::CatastrophicKill, structureElementIds);
|
||||
}
|
||||
|
||||
void BuildingEdit::getStructureElementIds(NGLTreeItem *item, std::vector<int32_t> &structureElementIds)
|
||||
{
|
||||
for (NGLTreeItem *child : item->children())
|
||||
getStructureElementIds(child, structureElementIds);
|
||||
|
||||
BuildingViewer::TreeItem data = item->data().value<TreeItem>();
|
||||
if (data.isRoom())
|
||||
structureElementIds.push_back(data.structureElementId());
|
||||
}
|
||||
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bdv_edit_model.h"
|
||||
|
||||
|
||||
#include <Common/logger.h>
|
||||
#include <Plugins/Buildings/bld_data_plugin_interface.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BuildingEdit;
|
||||
}
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BuildingEdit : public LtsWidgets::LtsDialog
|
||||
, protected Buildings::Interface::Ftc::SetFortifyFactorReplyHandler
|
||||
, protected Buildings::Interface::Ftc::SetBuildingStatesReplyHandler
|
||||
, protected InfrastructureManagement::Interface::Ftc::StructureElementModifyReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BuildingEdit(QWidget *parent = nullptr);
|
||||
~BuildingEdit();
|
||||
|
||||
bool init(int32_t buildingDatabaseId,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Ftc> &ismFtc,
|
||||
const std::shared_ptr<Buildings::Interface::Dtc> &bldDtc,
|
||||
const std::shared_ptr<Buildings::Interface::Ftc> &bldFtc);
|
||||
|
||||
void onSetFortifyFactorReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void onSetBuildingStatesReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void onStructureElementModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void selectRoomRow(int mountingPointId);
|
||||
|
||||
signals:
|
||||
void signalAccept();
|
||||
|
||||
private slots:
|
||||
void slotEditItem();
|
||||
void slotDoubleClicked(const QModelIndex &selIndex);
|
||||
void slotMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType);
|
||||
void slotBuildingStateChanged(const Buildings::BuildingState &state, DataModification modType);
|
||||
void slotHandleExternalDdsChange();
|
||||
void slotTreeViewClicked();
|
||||
|
||||
bool sendBuildingStateRequest(ProjectDataManagement::VulnerabilityState state, std::vector<int32_t> structureElementId);
|
||||
void onDestroyElement();
|
||||
|
||||
protected:
|
||||
void retranslate() override;
|
||||
bool apply() override;
|
||||
|
||||
private:
|
||||
void getStructureElementIds(NGLTreeItem *item, std::vector<int32_t> &structureElementIds);
|
||||
void buildModel();
|
||||
QModelIndex selectedIndexView() const;
|
||||
void reinitModel();
|
||||
|
||||
private:
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Ftc> m_ismFtc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
std::shared_ptr<Buildings::Interface::Ftc> m_bldFtc;
|
||||
|
||||
BuildingEditModel *m_model = nullptr;
|
||||
BuildingEditProxyModel *m_proxyModel = nullptr;
|
||||
LtsUtils::RequestHelper *m_requestHelper = nullptr;
|
||||
Ui::BuildingEdit *m_ui = nullptr;
|
||||
|
||||
QString m_buildingName;
|
||||
int32_t m_buildingDatabaseId = 0;
|
||||
int32_t m_buildingId = 0;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} //ParticipantManagement
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BuildingEdit</class>
|
||||
<widget class="QWidget" name="BuildingEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>279</width>
|
||||
<height>246</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">setwindowtitle in source</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTreeView" name="treeViewEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<attribute name="headerShowSortIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
#include "bdv_edit_item.h"
|
||||
#include "ui_bdv_edit_item.h"
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
ParticipantEditItemWidget::ParticipantEditItemWidget(const QString &buildingName,
|
||||
const BuildingViewer::TreeItem &itemValue,
|
||||
QWidget *parent)
|
||||
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
|
||||
, m_itemValue(itemValue)
|
||||
, m_ui(new Ui::BuildingEditItemWidget)
|
||||
, m_buttonBox(new LtsWidgets::LtsDialogButtonBox(this))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->leBuildingDescription->setText(buildingName);
|
||||
m_ui->leRoomDesription->setText(m_itemValue.displayName());
|
||||
m_ui->sbFortifyFactor->setValue(m_itemValue.fortifyFactor());
|
||||
|
||||
layout()->addWidget(m_buttonBox);
|
||||
connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Apply), &QPushButton::clicked, this, &ParticipantEditItemWidget::slotApply);
|
||||
connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, this, &ParticipantEditItemWidget::accept);
|
||||
|
||||
if ( itemValue.isBuilding() )
|
||||
{
|
||||
m_ui->lbBuildingName->hide();
|
||||
m_ui->leBuildingDescription->hide();
|
||||
m_ui->lbRoomDesription->setText(tr("Building Name:"));
|
||||
m_ui->sbFortifyFactor->setValue(1.0);
|
||||
}
|
||||
else if ( itemValue.isFloor() )
|
||||
{
|
||||
m_ui->lbRoomDesription->setText(tr("Floor:"));
|
||||
m_ui->sbFortifyFactor->setValue(1.0);
|
||||
}
|
||||
|
||||
//hide ok and apply
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->show();
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->hide();
|
||||
connect(m_ui->leRoomDesription, &QLineEdit::textChanged, this, [this]()
|
||||
{
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(true);
|
||||
});
|
||||
connect(m_ui->sbFortifyFactor, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, [this]()
|
||||
{
|
||||
m_fortifyFactorChanged = true;
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ParticipantEditItemWidget::~ParticipantEditItemWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void ParticipantEditItemWidget::slotApply()
|
||||
{
|
||||
if (m_ui->leRoomDesription->text().isEmpty())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Enter at least one character"));
|
||||
return;
|
||||
}
|
||||
|
||||
m_itemValue.setDisplayName(m_ui->leRoomDesription->text());
|
||||
|
||||
if (m_itemValue.isRoom() || !m_itemValue.hasDisplayNameChanged() || m_fortifyFactorChanged)
|
||||
m_itemValue.setFortifyFactor(m_ui->sbFortifyFactor->value());
|
||||
|
||||
if (m_itemValue.hasDisplayNameChanged() || m_itemValue.hasFortifyFactorChanged())
|
||||
emit signalItemUpdated(m_itemValue, m_fortifyFactorChanged);
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "bdv_treemodel_item.h"
|
||||
|
||||
#include <LtsWidgets/lts_frameless_dialog.h>
|
||||
#include <LtsWidgets/lts_dialog_button_box.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BuildingEditItemWidget;
|
||||
}
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
class ParticipantEditItemWidget : public LtsWidgets::LtsFramelessDialog
|
||||
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ParticipantEditItemWidget(const QString &buildingName,
|
||||
const TreeItem &itemValue,
|
||||
QWidget *parent = nullptr);
|
||||
~ParticipantEditItemWidget();
|
||||
|
||||
signals:
|
||||
void signalItemUpdated(const TreeItem &editData, const bool fortifyChanged);
|
||||
|
||||
private slots:
|
||||
void slotApply();
|
||||
|
||||
private:
|
||||
bool m_fortifyFactorChanged = false;
|
||||
TreeItem m_itemValue;
|
||||
Ui::BuildingEditItemWidget *m_ui;
|
||||
LtsWidgets::LtsDialogButtonBox *m_buttonBox;
|
||||
};
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BuildingEditItemWidget</class>
|
||||
<widget class="QWidget" name="BuildingEditItemWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>350</width>
|
||||
<height>109</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="sbFortifyFactor">
|
||||
<property name="toolTip">
|
||||
<string>Specify a value between 0 and 8</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>8.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.230000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lbFortifyFactor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fortify Factor:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="leBuildingDescription">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="leRoomDesription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>40</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbBuildingName">
|
||||
<property name="text">
|
||||
<string>Building Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lbRoomDesription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Room Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>17</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>leRoomDesription</tabstop>
|
||||
<tabstop>sbFortifyFactor</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
#include "bdv_edit_model.h"
|
||||
#include <Common/logger.h>
|
||||
#include <Services/InfrastructureManagement/ism.hpp>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QTableWidget>
|
||||
#include <QPalette>
|
||||
#include <QApplication>
|
||||
|
||||
#include <nglwidgets/ngltreeitem.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BuildingEditModel::BuildingEditModel(QObject *parent,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<Buildings::Interface::Dtc> &bldDtc)
|
||||
: NGLTreeModel(parent, new NGLTreeItem(QVariant()), {
|
||||
tr("Selected Building"),
|
||||
QStringLiteral("Name (DEBUG)"),
|
||||
QStringLiteral("MountingPointId (DEBUG)"),
|
||||
QStringLiteral("StructureElementId (DEBUG)"),
|
||||
tr("Fortify Factor"),
|
||||
tr("Damage Percent")})
|
||||
, m_ismDtc(ismDtc)
|
||||
, m_bldDtc(bldDtc)
|
||||
, m_buildingName(QString())
|
||||
, m_logger(getLogger("BuildingViewer::BuildingEdit"))
|
||||
{}
|
||||
|
||||
QVariant BuildingEditModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || (role != Qt::BackgroundRole && role != Qt::DisplayRole))
|
||||
return {};
|
||||
|
||||
|
||||
NGLTreeItem *pNGLTreeItem = privateData(index);
|
||||
|
||||
if (pNGLTreeItem->data().canConvert<BuildingViewer::TreeItem>())
|
||||
{
|
||||
BuildingViewer::TreeItem item = pNGLTreeItem->data().value<BuildingViewer::TreeItem>();
|
||||
|
||||
if (role == Qt::BackgroundRole)
|
||||
{
|
||||
if (item.hasDisplayNameChanged() || item.hasFortifyFactorChanged())
|
||||
return QGuiApplication::palette().color(QPalette::Highlight);
|
||||
}
|
||||
else if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case BuildingEditModel::Building: // Column "Building" also includes Floors and Rooms
|
||||
return item.displayName();
|
||||
case BuildingEditModel::Name:
|
||||
return item.name();
|
||||
case BuildingEditModel::MountingPointId:
|
||||
if (item.hasMountingPointId())
|
||||
return item.mountingPointId();
|
||||
break;
|
||||
case BuildingEditModel::StructureElementId:
|
||||
return item.structureElementId();
|
||||
case BuildingEditModel::FortifyFactor:
|
||||
if (item.isRoom())
|
||||
return QString::number(item.fortifyFactor(),'f',1);
|
||||
break;
|
||||
case BuildingEditModel::DamagePercent:
|
||||
if (item.isRoom())
|
||||
return QString::number(item.damagePercent());
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
bool BuildingEditModel::slotUpdateRow(const BuildingViewer::TreeItem &room, const bool fortifyChanged)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "slotUpdateRow isBuilding=" << room.isBuilding()
|
||||
<< " isFloor" << room.isFloor()
|
||||
<< " isRoom" << room.isRoom();
|
||||
|
||||
|
||||
QModelIndex idx = modelIndexByStructureElementId(room.structureElementId());
|
||||
|
||||
if (fortifyChanged && ( !room.isRoom() || !qFuzzyIsNull(room.fortifyFactor())))
|
||||
{
|
||||
for (auto *item : privateData(idx)->children())
|
||||
{
|
||||
TreeItem childItem = item->data().value<TreeItem>();
|
||||
childItem.setFortifyFactor(room.fortifyFactor());
|
||||
slotUpdateRow(childItem, fortifyChanged);
|
||||
}
|
||||
}
|
||||
|
||||
if (room.hasDisplayNameChanged())
|
||||
m_mapRoomsWithChangedDisplayName[room.structureElementId()] = room;
|
||||
if (fortifyChanged && (room.isRoom() && room.hasFortifyFactorChanged()))
|
||||
m_mapRoomsWithChangedFortifyFactor[room.structureElementId()] = room;
|
||||
|
||||
QVariant data;
|
||||
data.setValue(room);
|
||||
|
||||
emit signalModelDataChanged();
|
||||
return setItemData(idx, data, QIcon());
|
||||
}
|
||||
|
||||
|
||||
bool BuildingEditModel::onInsertRow(int &row, const QModelIndex &parent, const BuildingViewer::TreeItem &folderData)
|
||||
{
|
||||
row = rowCount(parent);
|
||||
QVariant data;
|
||||
data.setValue(folderData);
|
||||
NGLTreeItem *item = new NGLTreeItem(data, QIcon());
|
||||
item->setModified(true);
|
||||
|
||||
emit signalModelDataChanged();
|
||||
|
||||
return NGLTreeModel::insertRow(row, parent, item);
|
||||
}
|
||||
|
||||
|
||||
bool BuildingEditModel::init(int32_t mseId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "init mseId=" << mseId;
|
||||
NGLTreeModel::resetModel();
|
||||
m_mapRoomsWithChangedFortifyFactor.clear();
|
||||
|
||||
QMap<qint32, BuildingViewer::TreeItem> treemap;
|
||||
QMap<qint32, qint32> lookupFloorId2TreeId;
|
||||
QString rootName;
|
||||
|
||||
/*
|
||||
* Get Fortify Factors for current Building.
|
||||
* Important: Only the modified rooms (BuildingStates) are returned. E.g.,
|
||||
* if a building has 12 rooms and the fortify factor of 4 rooms have been changed in the past
|
||||
* 'm_mapRoomIdFortifyFactors' will only contain the ids auf these 4 rooms
|
||||
*/
|
||||
|
||||
// Retreive tree model data
|
||||
InfrastructureManagement::MainStructureElement building = m_ismDtc->mainStructureElement(mseId);
|
||||
int rootId = 0;
|
||||
qint32 mapId = 0;
|
||||
|
||||
const std::vector<InfrastructureManagement::StructureElement> &vecElements = building.elements();
|
||||
for (const auto &se : vecElements)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "se: " << se;
|
||||
if (se.structureElementTypeId() == InfrastructureManagement::StructureElementType::Building)
|
||||
{
|
||||
BuildingViewer::TreeItem rootItemBuilding(se);
|
||||
rootName =rootItemBuilding.name();
|
||||
m_buildingName = rootItemBuilding.displayName();
|
||||
mapId = rootId;
|
||||
treemap[mapId++] = rootItemBuilding;
|
||||
}
|
||||
}
|
||||
|
||||
//qint32 mapId = rootId;
|
||||
//BuildingViewer::TreeItem rootItemBuilding(building);
|
||||
//treemap[mapId++] = rootItemBuilding;
|
||||
|
||||
/*
|
||||
* The MainStructureElement, in our case the building, contains a vector which includes (among other things)
|
||||
* all floors and rooms belonging to this building. This vector may not be ordered. Hence, we first extract all
|
||||
* floors.
|
||||
*
|
||||
* Afterwards the same vector is iterated to identify all room. The map 'lookupFloorId2TreeId' is used to identify the
|
||||
* tree parent node (= Floor) of an identified room.
|
||||
*/
|
||||
// Identify building floors
|
||||
//const std::vector<InfrastructureManagement::StructureElement> &vecElements = building.elements();
|
||||
|
||||
for (const auto &se : vecElements)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "se: =" << se;
|
||||
if (se.structureElementTypeId() == InfrastructureManagement::StructureElementType_def::Floor)
|
||||
{
|
||||
BuildingViewer::TreeItem itemRoom(se);
|
||||
itemRoom.setSuperior(rootId);
|
||||
|
||||
lookupFloorId2TreeId[se.id()] = mapId;
|
||||
treemap[mapId++] = itemRoom;
|
||||
}
|
||||
}
|
||||
|
||||
m_bldDtc->enableBuildingState();
|
||||
m_bldDtc->waitForHistoricalDataBuildingState(1000);
|
||||
|
||||
auto bs = m_bldDtc->buildingState(mseId);
|
||||
|
||||
QMap<int32_t, Buildings::RoomState> roomStates;
|
||||
for (const auto &e : bs.roomStates())
|
||||
roomStates[e.id()] = e;
|
||||
|
||||
// Identify building rooms and assign them to the correct floors by using map 'lookupFloorId2TreeId'
|
||||
for (const auto &se : vecElements)
|
||||
{
|
||||
if (se.structureElementTypeId() == InfrastructureManagement::StructureElementType_def::Room)
|
||||
{
|
||||
// Default value if the fortify factor has not been changed so far (-> no entry in 'm_mapRoomIdFortifyFactors')
|
||||
double fortifyFactor = 1.0;
|
||||
qint32 damagePercent = bs.damagePercent();
|
||||
if (roomStates.contains(se.id()))
|
||||
{
|
||||
fortifyFactor = roomStates[se.id()].fortifyFactor();
|
||||
damagePercent = roomStates[se.id()].damagePercent();
|
||||
}
|
||||
|
||||
BuildingViewer::TreeItem itemRoom(se, fortifyFactor, damagePercent);
|
||||
|
||||
try
|
||||
{
|
||||
/*
|
||||
* A room belongs to a floor which belongs to a building. Hence, se.path().size() must contain
|
||||
* at least three elements:
|
||||
*
|
||||
* building id | floor id | room id
|
||||
*
|
||||
* Therefore it MUST be possible to directly access the floor id located at index 1.
|
||||
*/
|
||||
int32_t floorID = se.path()[1]; // Throws 'std::out_of_range' if 1 is out of bounds
|
||||
itemRoom.setSuperior(lookupFloorId2TreeId[floorID]);
|
||||
}
|
||||
catch (const std::out_of_range &e)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Caught exception while trying to get superior id for building " << rootName << " with room with mounting point id: " << se.mountingPointId() << ": " << e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
treemap[mapId++] = itemRoom;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, build Tree
|
||||
QHash<int, QPersistentModelIndex> parentItemIndexCache;
|
||||
parentItemIndexCache.insert(rootId, QModelIndex());
|
||||
|
||||
for (auto iter = treemap.constBegin(); iter != treemap.constEnd(); ++iter)
|
||||
{
|
||||
int itemDatabaseId = iter.key();
|
||||
const BuildingViewer::TreeItem &item = iter.value();
|
||||
|
||||
QVariant data;
|
||||
data.setValue(item);
|
||||
|
||||
int parentId = item.hasSuperior() ? item.getSuperior() : rootId;
|
||||
if (!parentItemIndexCache.contains(parentId))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid building structure! Tree can not be built!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QModelIndex pIndex = parentItemIndexCache.value(parentId);
|
||||
int rowPos = -1;
|
||||
|
||||
onInsertRow(rowPos, pIndex, item);
|
||||
|
||||
QPersistentModelIndex mIndex = index(rowPos, 0, pIndex);
|
||||
m_mapModelIndices[item.structureElementId()] = mIndex;
|
||||
parentItemIndexCache.insert(itemDatabaseId, mIndex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex BuildingEditModel::modelIndexByMountingPointId(int mountingPointId) const
|
||||
{
|
||||
for(const QPersistentModelIndex &mi : qAsConst(m_mapModelIndices))
|
||||
{
|
||||
if (privateData(mi)->data().value<TreeItem>().mountingPointId() == mountingPointId)
|
||||
return mi;
|
||||
}
|
||||
WARNING_LOG(m_logger)<<"Could not find modelindex for given room mountig point id: " << mountingPointId;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
QModelIndex BuildingEditModel::modelIndexByStructureElementId(int structureElementId) const
|
||||
{
|
||||
auto it = m_mapModelIndices.find(structureElementId);
|
||||
if (it == m_mapModelIndices.end())
|
||||
{
|
||||
WARNING_LOG(m_logger)<<"Could not find modelindex for given room structreElementId: " << structureElementId;
|
||||
return {};
|
||||
}
|
||||
return it.value();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void BuildingEditProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
m_sourceModel = qobject_cast<BuildingEditModel*>(sourceModel);
|
||||
QSortFilterProxyModel::setSourceModel(m_sourceModel);
|
||||
}
|
||||
|
||||
bool BuildingEditProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
if (!m_sourceModel ||
|
||||
left.column() != 0 || right.column() != 0)
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
|
||||
NGLTreeItem *itemLeft = m_sourceModel->privateData(left);
|
||||
NGLTreeItem *itemRight = m_sourceModel->privateData(right);
|
||||
if (itemLeft && itemRight)
|
||||
return (itemLeft->row() < itemRight->row());
|
||||
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
|
||||
|
||||
} //namespace BuildingViewer
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Common/logger.h>
|
||||
|
||||
#include <Plugins/Buildings/bld_data_plugin_interface.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
|
||||
#include "bdv_treemodel_item.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <functional>
|
||||
#include <nglwidgets/ngltreemodel.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BuildingEditModel : public NGLTreeModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
Building,
|
||||
Name,
|
||||
MountingPointId,
|
||||
StructureElementId,
|
||||
FortifyFactor,
|
||||
DamagePercent,
|
||||
ColumnCount,
|
||||
};
|
||||
|
||||
BuildingEditModel(QObject *parent,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<Buildings::Interface::Dtc> &bldDtc);
|
||||
|
||||
QList<BuildingViewer::TreeItem> getRoomsWithChangedFortifyFactors() const { return m_mapRoomsWithChangedFortifyFactor.values(); }
|
||||
QList<BuildingViewer::TreeItem> getRoomsWithChangedDisplayNames() const { return m_mapRoomsWithChangedDisplayName.values(); }
|
||||
|
||||
bool init(int32_t buildingDatabaseId);
|
||||
QModelIndex modelIndexByMountingPointId(int mountingPointId) const;
|
||||
QModelIndex modelIndexByStructureElementId(int structureElementId) const;
|
||||
QString getBuildingName() const {return m_buildingName;}
|
||||
|
||||
public slots:
|
||||
bool slotUpdateRow(const BuildingViewer::TreeItem &room, const bool fortifyChanged);
|
||||
|
||||
signals:
|
||||
void signalModelDataChanged(); // Causes the BuildingEdit apply button to get active
|
||||
|
||||
private:
|
||||
QVariant data(const QModelIndex &index, int role) const override final;
|
||||
bool onInsertRow(int &row, const QModelIndex &parent, const BuildingViewer::TreeItem &folderData);
|
||||
|
||||
QMap<int, QPersistentModelIndex> m_mapModelIndices; // room structureElementIds to tree QModelIndex
|
||||
|
||||
// SE-id to room
|
||||
QMap<int32_t, BuildingViewer::TreeItem> m_mapRoomsWithChangedFortifyFactor;
|
||||
QMap<int32_t, BuildingViewer::TreeItem> m_mapRoomsWithChangedDisplayName;
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
|
||||
QString m_buildingName;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class BuildingEditProxyModel final : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QSortFilterProxyModel::QSortFilterProxyModel;
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
private:
|
||||
BuildingEditModel *m_sourceModel = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BuildingViewer::TreeItem)
|
||||
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <Services/InfrastructureManagement/ism.hpp>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class TreeItem
|
||||
{
|
||||
public:
|
||||
TreeItem() = default;
|
||||
|
||||
// For Buildings
|
||||
explicit TreeItem(const InfrastructureManagement::MainStructureElement &mse)
|
||||
: m_displayName(toQString(mse.name()))
|
||||
, m_structureElementId(mse.id())
|
||||
, m_name(toQString(mse.name()) + QStringLiteral(" (ModelId: ") + QString::number(mse.modelId()) + QStringLiteral(")"))
|
||||
{}
|
||||
|
||||
// For Floors
|
||||
explicit TreeItem(const InfrastructureManagement::StructureElement &se)
|
||||
: m_displayName(toQString(se.displayName()))
|
||||
, m_isFloor(true)
|
||||
, m_structureElementId(se.id())
|
||||
, m_mountingPointId(se.mountingPointId())
|
||||
, m_name(toQString(se.name()))
|
||||
{}
|
||||
|
||||
// For Rooms
|
||||
explicit TreeItem(const InfrastructureManagement::StructureElement &se
|
||||
, double fortifyFactor
|
||||
, qint32 damagePercent)
|
||||
: m_displayName(toQString(se.displayName()))
|
||||
, m_fortifyFactor(fortifyFactor)
|
||||
, m_damagePercent(damagePercent)
|
||||
, m_isRoom(true)
|
||||
, m_structureElementId(se.id())
|
||||
, m_mountingPointId(se.mountingPointId())
|
||||
, m_name(toQString(se.name()))
|
||||
{}
|
||||
|
||||
int32_t structureElementId() const
|
||||
{
|
||||
return m_structureElementId;
|
||||
}
|
||||
|
||||
|
||||
bool hasSuperior() const
|
||||
{
|
||||
return m_hasSuperior;
|
||||
}
|
||||
|
||||
qint32 getSuperior() const
|
||||
{
|
||||
return m_superior;
|
||||
}
|
||||
|
||||
void setSuperior(int id)
|
||||
{
|
||||
m_hasSuperior = true;
|
||||
m_superior = id;
|
||||
}
|
||||
|
||||
bool hasMountingPointId() const
|
||||
{
|
||||
// The MainStructureElement has no mounting point id information
|
||||
return !isBuilding();
|
||||
}
|
||||
|
||||
bool isBuilding() const
|
||||
{
|
||||
return !m_hasSuperior;
|
||||
}
|
||||
|
||||
bool isFloor() const
|
||||
{
|
||||
return m_isFloor;
|
||||
}
|
||||
|
||||
bool isRoom() const
|
||||
{
|
||||
return m_isRoom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const QString &name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
void setStructureElementId(const int32_t structureElementId)
|
||||
{
|
||||
m_structureElementId = structureElementId;
|
||||
}
|
||||
|
||||
qint32 mountingPointId() const
|
||||
{
|
||||
return m_mountingPointId;
|
||||
}
|
||||
|
||||
void setDisplayName(const QString &strDisplayName)
|
||||
{
|
||||
m_displayNameChanged = m_displayNameChanged || (strDisplayName != m_displayName);
|
||||
m_displayName = strDisplayName;
|
||||
}
|
||||
|
||||
const QString &displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
|
||||
bool hasDisplayNameChanged() const
|
||||
{
|
||||
return m_displayNameChanged;
|
||||
}
|
||||
|
||||
void setFortifyFactor(double fortifyFactor)
|
||||
{
|
||||
m_fortifyFactorChanged = m_fortifyFactorChanged || !qFuzzyCompare(fortifyFactor, m_fortifyFactor);
|
||||
m_fortifyFactor = fortifyFactor;
|
||||
}
|
||||
|
||||
double fortifyFactor() const
|
||||
{
|
||||
return m_fortifyFactor;
|
||||
}
|
||||
|
||||
bool hasFortifyFactorChanged() const
|
||||
{
|
||||
return m_fortifyFactorChanged;
|
||||
}
|
||||
|
||||
void setDamagePercent(qint32 damagePercent)
|
||||
{
|
||||
m_damagePercentChanged = m_damagePercentChanged || (damagePercent != m_damagePercent);
|
||||
m_damagePercent = damagePercent;
|
||||
}
|
||||
|
||||
qint32 damagePercent() const
|
||||
{
|
||||
return m_damagePercent;
|
||||
}
|
||||
|
||||
bool hasDamagePercentChanged() const
|
||||
{
|
||||
return m_damagePercentChanged;
|
||||
}
|
||||
|
||||
private:
|
||||
static QString toQString(const std::string &strDds)
|
||||
{
|
||||
return QString::fromStdString(strDds);
|
||||
}
|
||||
|
||||
// DisplayName and FortifyFactor are different Dds Function Topic calls. Let's save some bandwidth
|
||||
QString m_displayName;
|
||||
double m_fortifyFactor = 0.0;
|
||||
qint32 m_damagePercent = 0;
|
||||
|
||||
bool m_displayNameChanged = false;
|
||||
bool m_fortifyFactorChanged = false;
|
||||
bool m_damagePercentChanged = false;
|
||||
|
||||
bool m_hasSuperior = false;
|
||||
qint32 m_superior = 0;
|
||||
|
||||
bool m_isFloor = false;
|
||||
bool m_isRoom = false;
|
||||
|
||||
int32_t m_structureElementId = 0;
|
||||
|
||||
qint32 m_mountingPointId = 0;
|
||||
QString m_name;
|
||||
};
|
||||
} // BuildingViewer
|
||||
@@ -0,0 +1,80 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Created by Mike Wille, SLSE, 2017-05-15
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
BuildingEdit/bdv_building_edit.cpp
|
||||
BuildingEdit/bdv_building_edit.h
|
||||
BuildingEdit/bdv_edit_item.cpp
|
||||
BuildingEdit/bdv_edit_item.h
|
||||
BuildingEdit/bdv_edit_model.cpp
|
||||
BuildingEdit/bdv_edit_model.h
|
||||
BuildingEdit/bdv_treemodel_item.h
|
||||
bdv_viewer_gui_plugin.h
|
||||
bdv_viewer_gui_plugin.cpp
|
||||
bdv_viewer_gui_plugin_provider.h
|
||||
bdv_viewer_gui_plugin_provider.cpp
|
||||
bdv_viewer_data_dialog.cpp
|
||||
bdv_viewer_data_dialog.h
|
||||
bdv_viewer_data_model.cpp
|
||||
bdv_viewer_data_model.h
|
||||
bdv_viewer_data_view.cpp
|
||||
bdv_viewer_data_view.h
|
||||
bdv_replay_handler.cpp
|
||||
bdv_replay_handler.h
|
||||
bdv_thread_video_exporter.cpp
|
||||
bdv_thread_video_exporter.h
|
||||
bdv_topic_replay_interface.cpp
|
||||
bdv_topic_replay_interface.h
|
||||
bdv_viewer_settings.cpp
|
||||
bdv_viewer_settings.h
|
||||
bdv_viewer_state_model.cpp
|
||||
bdv_viewer_state_model.h
|
||||
bdv_viewer_state.cpp
|
||||
bdv_viewer_state.h
|
||||
TopicEditor/topic_editor.cpp
|
||||
TopicEditor/topic_editor.h
|
||||
)
|
||||
|
||||
NGL_WRAP_UI(SRCS
|
||||
BuildingEdit/bdv_building_edit.ui
|
||||
BuildingEdit/bdv_edit_item.ui
|
||||
bdv_viewer_data_dialog.ui
|
||||
bdv_viewer_data_view.ui
|
||||
bdv_viewer_settings.ui
|
||||
bdv_viewer_state.ui
|
||||
TopicEditor/topic_editor.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS BdvViewerGuiPlugin MODULE ${SRCS})
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(BdvViewerGuiPlugin
|
||||
BdvViewerGuiPluginInterface
|
||||
BldDataPluginInterface
|
||||
BuildingViewerCommon
|
||||
PreScriptTimelineGuiPluginInterface # Export
|
||||
svcBldCommon
|
||||
svcBldClient
|
||||
svcAesClient
|
||||
svcSrpClient
|
||||
LtsDataView
|
||||
LtsPluginManager
|
||||
LtsScriptTimeline # TopicEditor
|
||||
LtsSession
|
||||
LtsWidgets
|
||||
NGLLogger
|
||||
nglwidgets
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
Qt5::Xml
|
||||
TopicEditorBase
|
||||
LtsUtilsGuiDds
|
||||
LtsUtilsSettings
|
||||
ngltools
|
||||
ExportBdvTopicSetting
|
||||
)
|
||||
NGL_INSTALL_TARGET(BdvViewerGuiPlugin)
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Philipp Last, SLSY, 2017-07-04
|
||||
*/
|
||||
|
||||
#include "topic_editor.h"
|
||||
#include "ui_topic_editor.h"
|
||||
|
||||
#include <Common/bdv_controller.h>
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
#include <LtsAppManager/lts_app_manager.h>
|
||||
#include <LtsPluginManager/lts_plugin_manager.h>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
TopicEditor::TopicEditor(LtsSession::LtsSession *session, BgViewerController *bgViewerController, BgViewerDataView *bgViewerDataView, QWidget *parent)
|
||||
: TopicEditorBase::TopicEditor(parent)
|
||||
, m_bgViewerController(bgViewerController)
|
||||
, m_bgViewerDataView(bgViewerDataView)
|
||||
, m_session(session)
|
||||
, m_ui(new Ui::BuildingViewerTopicEditor)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
init(m_ui->widget);
|
||||
|
||||
connect(m_bgViewerDataView, &BgViewerDataView::signalUserActionPerformend,
|
||||
this, &TopicEditor::slotChangesMade);
|
||||
|
||||
m_ui->verticalLayout->addWidget(m_bgViewerDataView);
|
||||
m_bgViewerController->closeBuilding();
|
||||
setOnlineHelpFilename(QStringLiteral("Script_Editor-Add_Building_Topic"));
|
||||
}
|
||||
|
||||
TopicEditor::~TopicEditor()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE
|
||||
|
||||
void TopicEditor::updateInternalData()
|
||||
{
|
||||
if (m_isFirst)
|
||||
QTimer::singleShot(1 * 1000, this, &TopicEditor::delayedStuff);
|
||||
else
|
||||
delayedStuff();
|
||||
}
|
||||
|
||||
void TopicEditor::delayedStuff()
|
||||
{
|
||||
if (hasTopicDataProperties())
|
||||
m_bgViewerController->excRestoreViewState(getTopicDataValue(QStringLiteral("arrBuildingStates")));
|
||||
m_bgViewerDataView->fetchBuildingList(); // Important to call this here to get a list with valid 'visible' attributes since 'excRestoreViewState' may have open some windows
|
||||
if (m_isFirst)
|
||||
__unchange__();
|
||||
|
||||
m_isFirst = false;
|
||||
}
|
||||
void TopicEditor::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Building Viewer Topic Editor"));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE SLOTS
|
||||
|
||||
bool TopicEditor::apply2()
|
||||
{
|
||||
connect(m_bgViewerController, &BgViewerController::signalReceivedViewState,
|
||||
this, &TopicEditor::onViewStateReceived, Qt::UniqueConnection);
|
||||
|
||||
if (m_session)
|
||||
{
|
||||
QVector<LtsPluginManager::LtsPluginManager *> plugManager = LtsAppManager::LtsAppManager::getInstance()->getAppList();
|
||||
for (auto pluginManager : plugManager )
|
||||
{
|
||||
for (auto session: pluginManager->sessions())
|
||||
{
|
||||
if( session->app() == LtsAppDescriptor::App::ScriptEditorEssentialsView)
|
||||
{
|
||||
LtsWidgets::LtsBaseLayoutWidget *blw = session->baseLayout();
|
||||
m_bgViewerSession = session;
|
||||
m_menuVisible = blw->isMenuVisible();
|
||||
m_topBarVisible = blw->isTopBarVisible();
|
||||
|
||||
// make room for a full sized geometry by removing the top bar, the detail bar and the menu - reshow after the image was successfully created
|
||||
blw->setMenuVisible(false);
|
||||
blw->setTopBarVisible(false);
|
||||
blw->hideVisibleLayouts();
|
||||
|
||||
QTimer::singleShot(5000, this, [this]()
|
||||
{
|
||||
if (m_bgViewerSession)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Asked for BgViewer Viewstate but no replay, resetting Layout";
|
||||
LtsWidgets::LtsBaseLayoutWidget *blw = m_bgViewerSession->baseLayout();
|
||||
blw->setMenuVisible(m_menuVisible);
|
||||
blw->setTopBarVisible(m_topBarVisible);
|
||||
blw->resetLayoutVisibility();
|
||||
m_bgViewerSession = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request view state from BgViewer process
|
||||
QTimer::singleShot(1000, this, [this]() { m_bgViewerController->excGetViewState(); } );
|
||||
|
||||
/*
|
||||
* P.L.: 'saveTopicData' darf hier NICHT direkt aufgerufen werden! saveTopicData darf erst aufgerufen werden,
|
||||
* wenn der externe BgViewer die Antwort auf obigen Aufruf von 'excGetViewState' gesendet hat.
|
||||
* Das wäre dann der slot 'onViewStateReceived'.
|
||||
*
|
||||
* Deswegen wird in dem slot auch der Zugriff auf 'm_widget' zwingend benoetigt.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TopicEditor::onViewStateReceived(const QJsonValue &state) // evaluates the response of 'excGetViewState'
|
||||
{
|
||||
disconnect(m_bgViewerController, &BgViewerController::signalReceivedViewState,
|
||||
this, &TopicEditor::onViewStateReceived);
|
||||
|
||||
if(m_bgViewerSession)
|
||||
{
|
||||
LtsWidgets::LtsBaseLayoutWidget *blw = m_bgViewerSession->baseLayout();
|
||||
blw->setMenuVisible(m_menuVisible);
|
||||
blw->setTopBarVisible(m_topBarVisible);
|
||||
blw->resetLayoutVisibility();
|
||||
m_bgViewerSession = nullptr;
|
||||
}
|
||||
|
||||
// if (m_ui->widget->description().isEmpty())
|
||||
// setDescription(!state.isArray() ? tr("No buildings selected") : tr("%n building(s) selected", "", state.toArray().size()));
|
||||
// else
|
||||
// setDescription(m_ui->widget->description());
|
||||
setDescription(m_ui->widget->description());
|
||||
setTopicDataProperty(QStringLiteral("arrBuildingStates"), state);
|
||||
m_ui->widget->setTopicData(m_topicData);
|
||||
applied();
|
||||
__unchange__();
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Philipp Last, SLSY, 2017-07-04
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Plugins/BuildingViewer/Gui/BuildingViewer/bdv_viewer_data_view.h>
|
||||
#include <TopicEditorBase/topic_editor_base.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
namespace Ui { class BuildingViewerTopicEditor; }
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
class BgViewerController;
|
||||
|
||||
|
||||
class TopicEditor : public TopicEditorBase::TopicEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TopicEditor(LtsSession::LtsSession *session, BgViewerController *bgViewerController, BgViewerDataView *bgViewerDataView, QWidget *parent = nullptr);
|
||||
~TopicEditor();
|
||||
|
||||
private:
|
||||
void updateInternalData() override final;
|
||||
void retranslate() override final;
|
||||
|
||||
private slots:
|
||||
bool apply2() override final;
|
||||
void delayedStuff();
|
||||
void onViewStateReceived(const QJsonValue &state);
|
||||
|
||||
private:
|
||||
BgViewerController *m_bgViewerController { nullptr };
|
||||
BgViewerDataView *m_bgViewerDataView { nullptr };
|
||||
LtsSession::LtsSession *m_session { nullptr };
|
||||
LtsSession::LtsSession *m_bgViewerSession { nullptr };
|
||||
bool m_isFirst = true;
|
||||
bool m_topBarVisible = false;
|
||||
bool m_menuVisible = false;
|
||||
Ui::BuildingViewerTopicEditor *m_ui { nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BuildingViewerTopicEditor</class>
|
||||
<widget class="QWidget" name="BuildingViewerTopicEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>742</width>
|
||||
<height>347</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Building Viewer Topic Editor</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="m_pLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="TopicEditorBase::TopicPreviewWidget" name="widget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TopicEditorBase::TopicPreviewWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>TopicEditorBase/topic_preview_widget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_replay_handler.h"
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
ReplayHandler::ReplayHandler(int buildingTopicStart_s, int buildingTopicEnd_s, const TopicReplay::Interface::SituationReplayTime &replay, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_actualReplayStart_ms(0)
|
||||
, m_actualReplayEnd_ms(0)
|
||||
, m_replayDuration_ms(0)
|
||||
, m_startOffset_ms(0)
|
||||
, m_replayInfo(replay)
|
||||
, m_logger(getLogger("ReplayHandler"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "buildingTopicStart_s = " << buildingTopicStart_s
|
||||
<< ", buildingTopicEnd_s = " << buildingTopicEnd_s
|
||||
<< ", replay.topicStart_s = " << replay.topicStart_s
|
||||
<< ", replay.topicEnd_s = " << replay.topicEnd_s
|
||||
<< ", replay.replayStart_ms = " << replay.replayStart_ms
|
||||
<< ", replay.replayEnd_ms = " << replay.replayEnd_ms;
|
||||
|
||||
// Identify actual replay start
|
||||
int start_diff_ms = (buildingTopicStart_s - replay.topicStart_s) * 1000;
|
||||
|
||||
if (start_diff_ms >= 0)
|
||||
{
|
||||
/*
|
||||
* Building topic is started with or after replay. This means,
|
||||
* the replay is already running.
|
||||
*/
|
||||
m_actualReplayStart_ms = replay.replayStart_ms + start_diff_ms;
|
||||
m_startOffset_ms = 0;
|
||||
DEBUG_LOG(m_logger) << "Replay starts before Building-Topic: Shift replay starting point to m_actualReplayStart_ms = " << m_actualReplayStart_ms;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Replay topic starts after the building topic is already playing.
|
||||
* Hence, we have to record the video first without any replay
|
||||
* and start the replay with an offset.
|
||||
*/
|
||||
m_actualReplayStart_ms = replay.replayStart_ms;
|
||||
m_startOffset_ms = std::abs(start_diff_ms);
|
||||
DEBUG_LOG(m_logger) << "Building-Topic starts before Replay: Starting Replay after " << m_startOffset_ms << "msec";
|
||||
}
|
||||
|
||||
// Identify actual replay end
|
||||
m_actualReplayEnd_ms = replay.replayEnd_ms;
|
||||
// Cut replay if it is running longer than the building topic
|
||||
if (replay.topicEnd_s > buildingTopicEnd_s)
|
||||
{
|
||||
m_actualReplayEnd_ms -= (replay.topicEnd_s - buildingTopicEnd_s) * 1000;
|
||||
DEBUG_LOG(m_logger) << "Replay longer than Building-Topic, cutting replay end to m_actualReplayEnd_ms = " << m_actualReplayEnd_ms;
|
||||
}
|
||||
|
||||
m_replayDuration_ms = m_actualReplayEnd_ms - m_actualReplayStart_ms;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Replay from " << m_actualReplayStart_ms << " to " << m_actualReplayEnd_ms << " (duration = " << m_replayDuration_ms << ")";
|
||||
|
||||
if (m_startOffset_ms == 0)
|
||||
m_startOffset_ms = -1; // Immediate start
|
||||
}
|
||||
|
||||
|
||||
void ReplayHandler::tick(qint64 diffSinceLastTick)
|
||||
{
|
||||
if (isExpired())
|
||||
return;
|
||||
|
||||
m_replayDuration_ms -= diffSinceLastTick;
|
||||
if (m_replayDuration_ms <= 0)
|
||||
{
|
||||
emit signalStopReplay();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "ReplayHandler::tick(): Remaining: " << m_replayDuration_ms << "msec";
|
||||
|
||||
if (m_startOffset_ms == -1)
|
||||
{
|
||||
emit signalStartReplay(m_actualReplayStart_ms, m_actualReplayEnd_ms, m_replayInfo.replaySpeedFactor);
|
||||
m_startOffset_ms = 0;
|
||||
}
|
||||
|
||||
if (m_startOffset_ms > 0)
|
||||
{
|
||||
m_startOffset_ms -= diffSinceLastTick;
|
||||
if (m_startOffset_ms <= 0)
|
||||
emit signalStartReplay(m_actualReplayStart_ms, m_actualReplayEnd_ms, m_replayInfo.replaySpeedFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <Plugins/SituationReplay/srp_gui_plugin_interface.h>
|
||||
#include <Plugins/BuildingViewer/bdv_viewer_gui_plugin_interface.h>
|
||||
#include <Plugins/BuildingViewer/Common/logger.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class ReplayHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ReplayHandler(int buildingTopicStart_s, int buildingTopicEnd_s, const TopicReplay::Interface::SituationReplayTime &replay, QObject *parent = nullptr);
|
||||
|
||||
void tick(qint64 diffSinceLastTick);
|
||||
|
||||
bool isExpired() const { return m_replayDuration_ms == 0; }
|
||||
|
||||
signals:
|
||||
void signalStartReplay(qint64 start, qint64 end, double speed);
|
||||
void signalStopReplay();
|
||||
|
||||
private:
|
||||
qint64 m_actualReplayStart_ms;
|
||||
qint64 m_actualReplayEnd_ms;
|
||||
|
||||
qint64 m_replayDuration_ms;
|
||||
qint64 m_startOffset_ms;
|
||||
TopicReplay::Interface::SituationReplayTime m_replayInfo;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_thread_video_exporter.h"
|
||||
#include "bdv_replay_handler.h"
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QThread>
|
||||
|
||||
#include <Common/TopicEditorBase/topic_editor_base.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
VideoExporter::VideoExporter(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_logger(getLogger("ThreadVideoExporter"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ThreadVideoExporter has been created";
|
||||
}
|
||||
|
||||
void VideoExporter::init(const VideoInformation &videoInfo)
|
||||
{
|
||||
m_vecVideosToExport.push_back(videoInfo);
|
||||
}
|
||||
|
||||
|
||||
void VideoExporter::sendAliveSignals()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendAliveSignals() called";
|
||||
|
||||
for (auto &e : qAsConst(m_vecVideosToExport))
|
||||
emit e.m_pExportNotifier->stillAlive();
|
||||
|
||||
DEBUG_LOG(m_logger) << "\tSignals emitted, mutex unlocked";
|
||||
}
|
||||
|
||||
|
||||
void VideoExporter::doExport()
|
||||
{
|
||||
while (!m_vecVideosToExport.isEmpty())
|
||||
{
|
||||
if (QThread::currentThread()->isInterruptionRequested())
|
||||
break;
|
||||
VideoInformation toExport = m_vecVideosToExport.takeFirst();
|
||||
DEBUG_LOG(m_logger) << "Starting export of " << toExport.m_strFolderPath;
|
||||
|
||||
const auto state = toExport.m_bgViewerState.value(QStringLiteral("arrBuildingStates"));
|
||||
|
||||
if (!state.isArray())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "No opened buildings, nothing to export, skipping video!";
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "Emitting 'signalStartRecording'";
|
||||
emit signalStartRecording(toExport.m_strFolderPath, state);
|
||||
|
||||
QSharedPointer<ReplayHandler> pHandler;
|
||||
|
||||
QElapsedTimer elapsedTimer;
|
||||
qint64 last_tick_elapsed = 0;
|
||||
qint64 elapsed_sum_ms = 0;
|
||||
const qint64 record_duration_ms = toExport.m_record_duration_s * 1000;
|
||||
|
||||
elapsedTimer.start();
|
||||
while (elapsed_sum_ms <= record_duration_ms)
|
||||
{
|
||||
const qint64 curElapsed = elapsedTimer.restart();
|
||||
elapsed_sum_ms += curElapsed;
|
||||
sendAliveSignals();
|
||||
emit toExport.m_pExportNotifier->stillAlive(); // Object behind 'toExport' is no longer included in vector, signal separately
|
||||
|
||||
if (!pHandler && toExport.m_vecReplayHandler.size())
|
||||
{
|
||||
pHandler = toExport.m_vecReplayHandler.front();
|
||||
connect(pHandler.data(), &ReplayHandler::signalStartReplay, this, &VideoExporter::signalStartReplay);
|
||||
connect(pHandler.data(), &ReplayHandler::signalStopReplay, this, &VideoExporter::signalStopReplay);
|
||||
toExport.m_vecReplayHandler.pop_front();
|
||||
}
|
||||
|
||||
const qint64 diff_ms = elapsed_sum_ms - last_tick_elapsed;
|
||||
|
||||
if (diff_ms >= 1000)
|
||||
{
|
||||
last_tick_elapsed = elapsed_sum_ms;
|
||||
DEBUG_LOG(m_logger) << "Export: " << elapsed_sum_ms / 1000 << "/" << record_duration_ms / 1000 << "[s] passed";
|
||||
}
|
||||
|
||||
if (pHandler)
|
||||
{
|
||||
pHandler->tick(curElapsed);
|
||||
|
||||
if (pHandler->isExpired())
|
||||
break;
|
||||
}
|
||||
QThread::msleep(100);
|
||||
if (QThread::currentThread()->isInterruptionRequested())
|
||||
break;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "Done. Emitting 'signalStopRecording'";
|
||||
emit signalStopRecording();
|
||||
|
||||
DEBUG_LOG(m_logger) <<"Export done, emitting 'signalExportSuccessful'";
|
||||
toExport.m_pExportNotifier->setExportSuccessful(toExport.m_strFolderPath);
|
||||
DEBUG_LOG(m_logger) <<"\tsignal emitted";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SituationReplay/srp_gui_plugin_interface.h>
|
||||
#include <BuildingViewer/bdv_viewer_gui_plugin_interface.h>
|
||||
#include <Common/logger.h>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class ReplayHandler;
|
||||
|
||||
class VideoInformation
|
||||
{
|
||||
public:
|
||||
VideoInformation() = default;
|
||||
VideoInformation(TopicEditorBase::ExportNotifier *pExportNotifier,
|
||||
const QString &strFolderPath,
|
||||
const QJsonObject &attributes,
|
||||
const QVector<QSharedPointer<ReplayHandler>> &vecReplayHandler,
|
||||
qint64 record_duration_s)
|
||||
: m_pExportNotifier(pExportNotifier)
|
||||
, m_record_duration_s(record_duration_s)
|
||||
, m_strFolderPath(strFolderPath)
|
||||
, m_bgViewerState(attributes)
|
||||
, m_vecReplayHandler(vecReplayHandler)
|
||||
{}
|
||||
|
||||
TopicEditorBase::ExportNotifier *m_pExportNotifier = nullptr;
|
||||
qint64 m_record_duration_s = -1;
|
||||
QString m_strFolderPath;
|
||||
QJsonObject m_bgViewerState;
|
||||
QVector<QSharedPointer<ReplayHandler>> m_vecReplayHandler;
|
||||
};
|
||||
|
||||
|
||||
class VideoExporter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VideoExporter(QObject *parent = nullptr);
|
||||
|
||||
void init(const VideoInformation &videoInfo);
|
||||
void doExport();
|
||||
|
||||
signals:
|
||||
void signalStartReplay(qint64 start, qint64 end, double speed);
|
||||
void signalStopReplay();
|
||||
|
||||
void signalStartRecording(const QString &strFolderPath, const QJsonValue &state);
|
||||
void signalStopRecording();
|
||||
|
||||
private:
|
||||
void sendAliveSignals();
|
||||
|
||||
QVector<VideoInformation> m_vecVideosToExport;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_topic_replay_interface.h"
|
||||
#include "bdv_viewer_gui_plugin.h"
|
||||
#include "bdv_thread_video_exporter.h"
|
||||
#include "bdv_replay_handler.h"
|
||||
#include <Common/bdv_controller.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QJsonDocument>
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
|
||||
#ifdef EXPORT_BDV_TOPIC_AS_JSON
|
||||
#include <QFile>
|
||||
#include <LtsUtilsCore/qpoint3d.h>
|
||||
#include <Common/bdv_helper.h>
|
||||
#include <Common/BgViewer/viewerCtrl/viewwidgetstate.h>
|
||||
#else
|
||||
#include <QThread>
|
||||
#endif
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
// Script Player
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
TopicReplayInterface::TopicReplayInterface(BgViewerController *bgvController, LtsSession::LtsSession *session)
|
||||
: m_bgvController(bgvController)
|
||||
, m_session(session)
|
||||
, m_logger(getLogger("TopicReplayInterface"))
|
||||
{
|
||||
session->getForeignGuiInterface<SituationReplay::ForeignGuiInterface>(m_replayIfc);
|
||||
}
|
||||
|
||||
|
||||
QWidget *TopicReplayInterface::createWidget()
|
||||
{
|
||||
delete m_pBgViewerWidget;
|
||||
m_pBgViewerWidget = m_bgvController ? m_bgvController->getBgViewerWidget() : nullptr;
|
||||
return m_pBgViewerWidget;
|
||||
}
|
||||
|
||||
|
||||
TopicReplayInterface::~TopicReplayInterface()
|
||||
{
|
||||
#ifndef EXPORT_BDV_TOPIC_AS_JSON
|
||||
if (m_tveThread)
|
||||
{
|
||||
m_tveThread->requestInterruption();
|
||||
m_tveThread->quit();
|
||||
m_tveThread->wait(20000);
|
||||
m_tveThread->terminate();
|
||||
}
|
||||
delete m_tveThread;
|
||||
#endif
|
||||
/*
|
||||
* deleteLater is not sufficient depending on the topic arrangement in skripteditor.
|
||||
* E.g., if a building topic should start directly after another building topic
|
||||
* deleteLater (and therefore releasing BgViewerWidget) will happen to late since
|
||||
* releasing and starting topics happens in one QTimer slot in SkriptPlayer
|
||||
*/
|
||||
delete m_pBgViewerWidget;
|
||||
m_pBgViewerWidget = nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool TopicReplayInterface::playbackInit(const QJsonObject &attributes)
|
||||
{
|
||||
if (!m_bgvController)
|
||||
return false;
|
||||
m_bgvController->closeBuilding();
|
||||
m_bgvController->excRestoreViewState(attributes.value(QStringLiteral("arrBuildingStates")));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TopicReplayInterface::slotStartReplay(qint64 start, qint64 end, double speed)
|
||||
{
|
||||
if (m_replayIfc)
|
||||
m_replayIfc->startReplay(start, end, speed);
|
||||
}
|
||||
|
||||
void TopicReplayInterface::slotStopReplay()
|
||||
{
|
||||
if (m_replayIfc)
|
||||
m_replayIfc->stopReplay();
|
||||
}
|
||||
|
||||
|
||||
void TopicReplayInterface::setExportPlaybackTimes(qint64 startTimeSec,
|
||||
qint64 durationSec,
|
||||
const QVector<SituationReplayTime> &sitReplayTimes)
|
||||
{
|
||||
m_startTimeSec = startTimeSec;
|
||||
m_durationSec = durationSec;
|
||||
m_sitReplayTimes = sitReplayTimes;
|
||||
}
|
||||
|
||||
bool TopicReplayInterface::exportTopic(const QJsonObject &attributes,
|
||||
const QString &folderPath,
|
||||
TopicEditorBase::ExportNotifier *pExportNotifier)
|
||||
{
|
||||
#ifdef EXPORT_BDV_TOPIC_AS_JSON
|
||||
const QJsonArray states = attributes[QStringLiteral("arrBuildingStates")].toArray();
|
||||
if (states.isEmpty())
|
||||
{
|
||||
INFO_LOG(m_logger) << "Nothing to export";
|
||||
emit pExportNotifier->exportSuccessful(QString());
|
||||
return true;
|
||||
}
|
||||
|
||||
const QString filename(QStringLiteral("buildingViewer.json"));
|
||||
QFile f(folderPath + QLatin1Char('/') + filename);
|
||||
if (!f.open(QIODevice::WriteOnly))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Can not open file '" << f.fileName() << "' for writing!";
|
||||
pExportNotifier->setExportFailed();
|
||||
return false;
|
||||
}
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("attributes")] = attributes;
|
||||
obj[QStringLiteral("timeInPresentation")] = timeRange(m_startTimeSec * 1000,
|
||||
(m_startTimeSec + m_durationSec) * 1000);
|
||||
|
||||
QJsonArray arr;
|
||||
for (const SituationReplayTime &rt : qAsConst(m_sitReplayTimes))
|
||||
{
|
||||
if (m_startTimeSec > rt.topicEnd_s)
|
||||
continue;
|
||||
const double lenReplay = rt.replayEnd_ms - rt.replayStart_ms;
|
||||
const double endReplay = rt.replayStart_ms + lenReplay;
|
||||
// TODO: check - looks not correct
|
||||
const double maxReplay = std::min(rt.replayStart_ms + m_durationSec * 1000. * rt.replaySpeedFactor, endReplay);
|
||||
arr.push_back(rt.toJson(maxReplay));
|
||||
}
|
||||
obj[QStringLiteral("replays")] = arr;
|
||||
f.write(QJsonDocument(obj).toJson(QJsonDocument::Indented));
|
||||
f.close();
|
||||
DEBUG_LOG(m_logger) << "BDV filename: " << f.fileName();
|
||||
|
||||
QVector<int> buildingIds;
|
||||
buildingIds.reserve(states.size());
|
||||
for (const auto &ele : states)
|
||||
{
|
||||
const ViewWidgetState vws(ele.toObject());
|
||||
int buildingId = featureId2DatabaseId(QString::fromStdString(vws.m_featureID));
|
||||
if (buildingId <= 0)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not retrieve building id from '" << vws.m_featureID << "' - skipping";
|
||||
continue;
|
||||
}
|
||||
buildingIds += buildingId;
|
||||
}
|
||||
|
||||
emit pExportNotifier->stillAlive();
|
||||
if (!exportBuildings(buildingIds) ||
|
||||
!exportShaders())
|
||||
{
|
||||
pExportNotifier->setExportFailed();
|
||||
return false;
|
||||
}
|
||||
//COPY buildings into directory
|
||||
const QString outputPath(m_basePath + QStringLiteral("BuildingModels/"));
|
||||
QFile fBdv(outputPath + QStringLiteral("/buildings.json"));
|
||||
if (fBdv.exists())
|
||||
{
|
||||
fBdv.copy(folderPath + QStringLiteral("/../buildings.json"));
|
||||
}
|
||||
|
||||
emit pExportNotifier->exportSuccessful(filename);
|
||||
#else
|
||||
// Assumes that the essentials view is open
|
||||
if (!m_replayIfc || !m_bgvController)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "BuildingViewer exportTopic: m_replayIfc==nullptr, can not start replay, aborting export";
|
||||
emit pExportNotifier->exportFailed();
|
||||
Q_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
playbackInit(attributes);
|
||||
|
||||
qint64 record_duration_s = m_durationSec + 2; // Add 2 seconds since actual output seems always to be shorter than desired
|
||||
// Get replays for building (if any)
|
||||
QVector<QSharedPointer<ReplayHandler>> vecReplayHandler;
|
||||
vecReplayHandler.reserve(m_sitReplayTimes.size());
|
||||
for (const SituationReplayTime &srt : qAsConst(m_sitReplayTimes))
|
||||
vecReplayHandler.push_back(QSharedPointer<ReplayHandler>(new ReplayHandler(m_startTimeSec, m_startTimeSec + m_durationSec, srt)));
|
||||
|
||||
VideoInformation info(pExportNotifier, folderPath, attributes, vecReplayHandler, record_duration_s);
|
||||
|
||||
VideoExporter *videoExporter = new VideoExporter;
|
||||
videoExporter->init(info);
|
||||
|
||||
Q_ASSERT(!m_tveThread);
|
||||
m_tveThread = new QThread(this);
|
||||
videoExporter->moveToThread(m_tveThread);
|
||||
|
||||
connect(videoExporter, &VideoExporter::signalStartReplay,
|
||||
this, &TopicReplayInterface::slotStartReplay);
|
||||
connect(videoExporter, &VideoExporter::signalStopReplay,
|
||||
this, &TopicReplayInterface::slotStopReplay);
|
||||
|
||||
/*
|
||||
* Qt::BlockingQueuedConnection
|
||||
* Same as Qt::QueuedConnection, except that the signaling thread blocks until the slot returns.
|
||||
* This connection must not be used if the receiver lives in the signalling thread, or else the application will deadlock.
|
||||
*
|
||||
* -> Video thread signals "startrecording" and waits until 'slotStartRecording' in main thread has been processed
|
||||
*/
|
||||
connect(videoExporter, &VideoExporter::signalStartRecording,
|
||||
m_bgvController, &BgViewerController::slotStartRecording, Qt::BlockingQueuedConnection);
|
||||
connect(videoExporter, &VideoExporter::signalStopRecording,
|
||||
m_bgvController, &BgViewerController::slotStopRecording, Qt::BlockingQueuedConnection);
|
||||
|
||||
connect(m_tveThread, &QThread::started, videoExporter, &VideoExporter::doExport);
|
||||
connect(m_tveThread, &QThread::finished, videoExporter, &VideoExporter::deleteLater);
|
||||
|
||||
m_tveThread->start();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TopicReplayInterface::exportBuildings(const QVector<int> &buildingIds) const
|
||||
{
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc))
|
||||
return false;
|
||||
const QString modelPath = BgViewerController::buildingModelPath();
|
||||
if (modelPath.isEmpty())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find path with building models - can not copy models";
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString outputPath(m_basePath + QStringLiteral("BuildingModels/"));
|
||||
QDir dir(outputPath);
|
||||
if (!dir.exists() && !dir.mkpath(outputPath))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not create path " << outputPath;
|
||||
return false;
|
||||
}
|
||||
QFile f(outputPath + QStringLiteral("/buildings.json"));
|
||||
if (!f.open(QIODevice::ReadWrite))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not open file " << f.fileName() << " for read/write: " << f.errorString();
|
||||
return false;
|
||||
}
|
||||
const QJsonArray arr(QJsonDocument::fromJson(f.readAll()).array());
|
||||
QVector<BuildingInfo> knownBuildings;
|
||||
knownBuildings.reserve(arr.size());
|
||||
for (const auto &ele : arr)
|
||||
{
|
||||
const auto bi = BuildingInfo::fromJson(ele.toObject());
|
||||
if (bi.isValid())
|
||||
knownBuildings += bi;
|
||||
}
|
||||
|
||||
BuildingInfo bi;
|
||||
for (const int buildingId : buildingIds)
|
||||
{
|
||||
const auto mse = ismDtc->mainStructureElement(buildingId);
|
||||
if (mse.id() != buildingId)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find MainStructureElement for building with id " << buildingId << " - skipping";
|
||||
continue;
|
||||
}
|
||||
const QString fnIve = QString::fromStdString(mse.name()) + QStringLiteral(".flt.ive");
|
||||
const QString fnXml = QString::fromStdString(mse.name()) + QStringLiteral(".flt.xml");
|
||||
if (!copyFile(fnIve, modelPath, outputPath) ||
|
||||
!copyFile(fnXml, modelPath, outputPath))
|
||||
return false;
|
||||
bi.name = QString::fromStdString(mse.name());
|
||||
bi.position = LtsUtils::QPoint3D(mse.geoPosition().lon(), mse.geoPosition().lat(), mse.geoPosition().z());
|
||||
bi.angleDegree = mse.angle();
|
||||
bi.id = mse.id();
|
||||
|
||||
knownBuildings += bi;
|
||||
}
|
||||
|
||||
std::sort(knownBuildings.begin(), knownBuildings.end(),
|
||||
[](const BuildingInfo &a, const BuildingInfo &b)
|
||||
{
|
||||
return a.id < b.id;
|
||||
});
|
||||
knownBuildings.erase(std::unique(knownBuildings.begin(), knownBuildings.end()), knownBuildings.end());
|
||||
QJsonArray arrOut;
|
||||
for (const auto &b : qAsConst(knownBuildings))
|
||||
arrOut += b.toJson();
|
||||
|
||||
f.resize(0);
|
||||
f.seek(0);
|
||||
f.write(QJsonDocument(arrOut).toJson());
|
||||
f.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TopicReplayInterface::exportShaders() const
|
||||
{
|
||||
const QString shaderPath(NGL::findFile(NGL::FileType::ConfigFile, QStringLiteral("shaders")));
|
||||
const QString outputPath(m_basePath + QStringLiteral("BuildingModels/shaders/"));
|
||||
DEBUG_LOG(m_logger) << "shaderPath: " << shaderPath << ", outputPath: " << outputPath;
|
||||
return NGL::copyDirContentsToDir(shaderPath, outputPath);
|
||||
}
|
||||
|
||||
|
||||
bool TopicReplayInterface::copyFile(const QString &srcFn, const QString &srcDir, const QString &dstDir) const
|
||||
{
|
||||
const QString src = srcDir + QLatin1Char('/') + srcFn;
|
||||
const QString dst = dstDir + QLatin1Char('/') + srcFn;
|
||||
QFile f(src);
|
||||
if (!f.exists() || (!QFile::exists(dst) && !f.copy(dst)))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not copy " << src << " to " << dst << ": " << f.errorString();
|
||||
return false;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "Copied from " << src << " to " << dst;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <Plugins/SituationReplay/srp_gui_plugin_interface.h>
|
||||
#include <Plugins/BuildingViewer/bdv_viewer_gui_plugin_interface.h>
|
||||
#include <memory>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class InterfaceImpl;
|
||||
class BgViewerController;
|
||||
|
||||
//Scriptplayer
|
||||
class TopicReplayInterface final : public QObject, public TopicReplay::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TopicReplayInterface(BgViewerController *bgvController, LtsSession::LtsSession *session);
|
||||
~TopicReplayInterface();
|
||||
|
||||
QWidget *createWidget() override;
|
||||
bool playbackInit(const QJsonObject &attributes) override;
|
||||
void setExportPlaybackTimes(qint64 startTimeSec,
|
||||
qint64 durationSec,
|
||||
const QVector<SituationReplayTime> &sitReplayTimes) override;
|
||||
bool exportTopic(const QJsonObject &attributes,
|
||||
const QString &folderPath,
|
||||
TopicEditorBase::ExportNotifier *pExportNotifier) override;
|
||||
|
||||
void setBasePath(const QString &basePath) override { m_basePath = basePath; }
|
||||
|
||||
private slots:
|
||||
void slotStartReplay(qint64 start, qint64 end, double speed);
|
||||
void slotStopReplay();
|
||||
private:
|
||||
bool exportBuildings(const QVector<int> &buildingIds) const;
|
||||
bool exportShaders() const;
|
||||
bool copyFile(const QString &srcFn, const QString &srcDir, const QString &dstDir) const;
|
||||
private:
|
||||
qint64 m_startTimeSec = 0;
|
||||
qint64 m_durationSec = 0;
|
||||
QVector<SituationReplayTime> m_sitReplayTimes;
|
||||
std::shared_ptr<SituationReplay::ForeignGuiInterface> m_replayIfc;
|
||||
QString m_basePath;
|
||||
QWidget *m_pBgViewerWidget = nullptr;
|
||||
#ifndef EXPORT_BDV_TOPIC_AS_JSON
|
||||
QThread *m_tveThread = nullptr;
|
||||
#endif
|
||||
BgViewerController *m_bgvController = nullptr;
|
||||
LtsSession::LtsSession *m_session = nullptr;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_data_dialog.h"
|
||||
#include "ui_bdv_viewer_data_dialog.h"
|
||||
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <Proxies/Buildings/bld_operator_rights.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerDataViewDialog::BgViewerDataViewDialog(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_ui(new Ui::BgViewerDataViewDialog)
|
||||
, m_logger(getLogger("BgViewerDataViewDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
bool userHasRightsToEdit = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BuildingViewerSettingsEdit);
|
||||
if (!userHasRightsToEdit)
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setText(tr("Show details"));
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, m_ui->widget, &BgViewerDataView::onLtsDataView_onEditBuilding);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Show, m_ui->widget, &BgViewerDataView::onLtsDataView_DoubleClicked);
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Show)->setEnabled(false);
|
||||
connect(m_ui->widget, &BgViewerDataView::signalCurrentSelectionChanged, this, [this](const QModelIndex & idx)
|
||||
{
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(idx.isValid());
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Show)->setEnabled(idx.isValid());
|
||||
});
|
||||
|
||||
connect(m_ui->widget, &BgViewerDataView::signalEditBuilding,
|
||||
this, &BgViewerDataViewDialog::signalEditBuilding);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Building_Viewer-Building_List"));
|
||||
}
|
||||
|
||||
|
||||
BgViewerDataViewDialog::~BgViewerDataViewDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void BgViewerDataViewDialog::fetchBuildingList()
|
||||
{
|
||||
m_ui->widget->fetchBuildingList();
|
||||
}
|
||||
|
||||
bool BgViewerDataViewDialog::init(BgViewerController *pBdvController,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
bool fetchBuildingDataOnCreation)
|
||||
{
|
||||
return m_ui->widget->init(pBdvController, ismDtc, fetchBuildingDataOnCreation);
|
||||
}
|
||||
|
||||
void BgViewerDataViewDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Building List"));
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <Common/logger.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BgViewerDataViewDialog;
|
||||
}
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerController;
|
||||
|
||||
class BgViewerDataViewDialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BgViewerDataViewDialog(QWidget *parent = nullptr);
|
||||
~BgViewerDataViewDialog();
|
||||
|
||||
bool init(BgViewerController *pBdvController,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
bool fetchBuildingDataOnCreation);
|
||||
|
||||
public Q_SLOTS:
|
||||
void fetchBuildingList();
|
||||
protected:
|
||||
void retranslate() override;
|
||||
|
||||
signals:
|
||||
void signalEditBuilding(const QString &strFeatureID);
|
||||
|
||||
private:
|
||||
Ui::BgViewerDataViewDialog *m_ui;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BgViewerDataViewDialog</class>
|
||||
<widget class="QWidget" name="BgViewerDataViewDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>18</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="BuildingViewer::BgViewerDataView" name="widget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BuildingViewer::BgViewerDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>bdv_viewer_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for ParticipantManagement - Party Overview Model
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_data_model.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QPalette>
|
||||
#include <QGuiApplication>
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerDataViewModel::BgViewerDataViewModel(QObject *parent)
|
||||
: LtsAbstractTableModel({
|
||||
tr("Id"),
|
||||
tr("Feature Id"),
|
||||
tr("Visible"),
|
||||
tr("Description"),
|
||||
QStringLiteral("Entity Id")
|
||||
},
|
||||
parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataViewModel::onViewerEventWidgetClosed(const QString &buildingId)
|
||||
{
|
||||
for (int row = 0; row < m_vecData.size(); ++row)
|
||||
{
|
||||
if (m_vecData.at(row).buildingId == buildingId)
|
||||
{
|
||||
m_vecData[row].isShown = false;
|
||||
emit dataChanged(index(row, 0), index(row, eColEntityId), {Qt::DisplayRole, Qt::BackgroundRole});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QModelIndex BgViewerDataViewModel::getModelIndex(const QString &buildingId) const
|
||||
{
|
||||
for (int row = 0; row < m_vecData.size(); ++row)
|
||||
{
|
||||
if (m_vecData[row].buildingId == buildingId)
|
||||
return index(row, 0);
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
|
||||
QVariant BgViewerDataViewModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if ((role != Qt::BackgroundRole && role != Qt::DisplayRole) || !indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
const BuildingTuple &row = m_vecData.at(index.row());
|
||||
if (role == Qt::BackgroundRole)
|
||||
{
|
||||
if (row.isShown)
|
||||
return QGuiApplication::palette().color(QPalette::Highlight);
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case eColId:
|
||||
return index.row() + 1;
|
||||
case eColFeatureId:
|
||||
return row.buildingId;
|
||||
case eColVisible:
|
||||
return row.isShown ? tr("Yes") : tr("No");
|
||||
case eColDescription:
|
||||
return row.description;
|
||||
case eColEntityId:
|
||||
return row.entityId;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <Common/bdv_helper.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class ForeignDataInterface;
|
||||
|
||||
class BgViewerDataViewModel : public LtsWidgets::LtsAbstractTableModel<BuildingTuple>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
eColId,
|
||||
eColFeatureId,
|
||||
eColVisible,
|
||||
eColDescription,
|
||||
eColEntityId
|
||||
};
|
||||
explicit BgViewerDataViewModel(QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QModelIndex getModelIndex(const QString &buildingId) const;
|
||||
|
||||
public slots:
|
||||
void onViewerEventWidgetClosed(const QString &buildingId);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_data_view.h"
|
||||
#include "ui_bdv_viewer_data_view.h"
|
||||
#include "bdv_viewer_data_model.h"
|
||||
|
||||
#include <Common/bdv_controller.h>
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerDataView::BgViewerDataView(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::BgViewerDataView)
|
||||
, m_pModel(new BgViewerDataViewModel(this))
|
||||
, m_logger(getLogger("BgViewerDataView"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->widget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked, this, &BgViewerDataView::onLtsDataView_DoubleClicked);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalEnterPressed, this, &BgViewerDataView::onLtsDataView_DoubleClicked);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged, this, &BgViewerDataView::onLtsDataView_selectionChanged);
|
||||
|
||||
m_ui->widget->setModel(m_pModel);
|
||||
m_ui->widget->installEventFilter(this);
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
m_ui->widget->hideColumn(BgViewerDataViewModel::eColId);
|
||||
m_ui->widget->hideColumn(BgViewerDataViewModel::eColEntityId);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
BgViewerDataView::~BgViewerDataView()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
bool BgViewerDataView::init(BgViewerController *pBgvController,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
bool fetchBuildingDataOnCreation)
|
||||
{
|
||||
if (!pBgvController || !ismDtc)
|
||||
return false;
|
||||
|
||||
if (m_pBgvController)
|
||||
{
|
||||
m_pBgvController->disconnect(this);
|
||||
m_pBgvController->disconnect(m_pModel);
|
||||
}
|
||||
m_pBgvController = pBgvController;
|
||||
connect(ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
|
||||
this, &BgViewerDataView::fetchBuildingList, Qt::UniqueConnection);
|
||||
connect(m_pBgvController, &BgViewerController::signalReceivedBuildingList,
|
||||
m_pModel, &BgViewerDataViewModel::setData);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventWidgetMaximized,
|
||||
this, &BgViewerDataView::onViewerEventWidgetMaximized);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventWidgetFocused,
|
||||
this, &BgViewerDataView::onViewerEventWidgetFocused);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventWidgetClosed,
|
||||
this, &BgViewerDataView::signalUserActionPerformend);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventWidgetClosed,
|
||||
m_pModel, &BgViewerDataViewModel::onViewerEventWidgetClosed);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerZoomChanged,
|
||||
this, &BgViewerDataView::signalUserActionPerformend);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventButton,
|
||||
this, &BgViewerDataView::signalUserActionPerformend);
|
||||
|
||||
if (fetchBuildingDataOnCreation)
|
||||
fetchBuildingList();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BgViewerDataView::fetchBuildingList()
|
||||
{
|
||||
m_pBgvController->excGetBuildingList();
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onViewerEventWidgetMaximized(const QString &featureID)
|
||||
{
|
||||
QModelIndex idx = m_pModel->getModelIndex(featureID);
|
||||
|
||||
if (idx.isValid())
|
||||
{
|
||||
m_ui->widget->selectRow(idx);
|
||||
emit signalUserActionPerformend();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onViewerEventWidgetFocused(const QString &featureID)
|
||||
{
|
||||
QModelIndex idx = m_pModel->getModelIndex(featureID);
|
||||
|
||||
if (idx.isValid())
|
||||
m_ui->widget->selectRow(idx);
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerDataView::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if (object == m_ui->widget)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *pKeyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (pKeyEvent->key() == Qt::Key_Delete)
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
|
||||
if (idx.row() >= 0)
|
||||
{
|
||||
BuildingTuple row = m_pModel->getRowData(idx.row());
|
||||
m_pBgvController->closeBuilding(row.buildingId);
|
||||
emit signalUserActionPerformend();
|
||||
}
|
||||
}
|
||||
else if (pKeyEvent->key() == Qt::Key_F5)
|
||||
fetchBuildingList();
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(object, event);
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onLtsDataView_DoubleClicked()
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
|
||||
if (idx.row() >= 0)
|
||||
{
|
||||
BuildingTuple row = m_pModel->getRowData(idx.row());
|
||||
|
||||
/* Try to open the requested building in any case.
|
||||
* If it is not opened, it will be opened.
|
||||
* If it is already opened, it will be highlighted
|
||||
*/
|
||||
m_pBgvController->openBuilding(row.buildingId);
|
||||
emit signalUserActionPerformend();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onLtsDataView_selectionChanged()
|
||||
{
|
||||
/*
|
||||
* This function is not only called when "a selection changed" (as assumed) but also
|
||||
* if the user, e.g., double clicks on a row. Hence, we check the column here again.
|
||||
*/
|
||||
const auto mil = m_ui->widget->selectedRows();
|
||||
|
||||
if (mil.size() == 1)
|
||||
{
|
||||
const auto &idx = mil.first();
|
||||
if (idx.row() != m_lastSelectedRow)
|
||||
{
|
||||
m_lastSelectedRow = idx.row();
|
||||
BuildingTuple row = m_pModel->getRowData(idx.row());
|
||||
m_pBgvController->excHighlightView(row.buildingId);
|
||||
emit signalCurrentSelectionChanged(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onLtsDataView_onEditBuilding()
|
||||
{
|
||||
const auto mil = m_ui->widget->selectedRows();
|
||||
if (mil.size() == 1)
|
||||
{
|
||||
BuildingTuple row = m_pModel->getRowData(mil.first().row());
|
||||
emit signalEditBuilding(row.buildingId);
|
||||
emit signalUserActionPerformend();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <Common/logger.h>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BgViewerDataView;
|
||||
}
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerDataViewModel;
|
||||
class BgViewerController;
|
||||
|
||||
class BgViewerDataView final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BgViewerDataView(QWidget *parent = nullptr);
|
||||
~BgViewerDataView();
|
||||
|
||||
bool init(BgViewerController *pBgvController,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
bool fetchBuildingDataOnCreation);
|
||||
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
public slots:
|
||||
void fetchBuildingList();
|
||||
void onLtsDataView_DoubleClicked();
|
||||
void onLtsDataView_selectionChanged();
|
||||
void onLtsDataView_onEditBuilding();
|
||||
|
||||
signals:
|
||||
void signalUserActionPerformend(); // Emitted when user open, closes, etc. a building view. Solely used by the topic editor to detect changes and to enable the "Apply" button
|
||||
void signalCurrentSelectionChanged(const QModelIndex &idx);
|
||||
void signalEditBuilding(const QString &strFeatureID);
|
||||
|
||||
|
||||
public slots:
|
||||
void onViewerEventWidgetMaximized(const QString &featureID);
|
||||
void onViewerEventWidgetFocused(const QString &featureID);
|
||||
|
||||
private:
|
||||
Ui::BgViewerDataView *m_ui = nullptr;
|
||||
BgViewerDataViewModel *m_pModel = nullptr;
|
||||
BgViewerController *m_pBgvController = nullptr;
|
||||
int m_lastSelectedRow { -1 };
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BgViewerDataView</class>
|
||||
<widget class="QWidget" name="BgViewerDataView">
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="widget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,551 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2017-05-15
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_gui_plugin.h"
|
||||
|
||||
#include <Proxies/Buildings/bld_operator_rights.h>
|
||||
#include <Plugins/BuildingViewer/Common/logger.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsWidgets/lts_splash.h>
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
#include <LtsAppManager/lts_app_manager.h>
|
||||
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "bdv_viewer_data_dialog.h"
|
||||
#include "bdv_viewer_data_view.h"
|
||||
#include "BuildingEdit/bdv_building_edit.h"
|
||||
#include "bdv_viewer_state.h"
|
||||
#include "bdv_viewer_settings.h"
|
||||
#include "bdv_replay_handler.h"
|
||||
#include "bdv_thread_video_exporter.h"
|
||||
#include "bdv_topic_replay_interface.h"
|
||||
#include "bdv_viewer_gui_plugin_provider.h"
|
||||
|
||||
#include <Common/bdv_helper.h>
|
||||
#include <Common/bdv_controller.h>
|
||||
#include <Common/bdv_plugin_provider.h>
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<BuildingViewer::InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, getLogger("InterfaceImpl"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::init()
|
||||
{
|
||||
connect(this, &InterfaceImpl::signalInitDone,
|
||||
m_session, &LtsSession::LtsSession::slotPluginInitDone,
|
||||
static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
|
||||
|
||||
connect (m_session, &LtsSession::LtsSession::sessionAboutToBeDestroyed,
|
||||
this, &InterfaceImpl::closeAll);
|
||||
|
||||
connect(m_session, &LtsSession::LtsSession::signalTakeOverBdv,
|
||||
this, &InterfaceImpl::takeOverBdv);
|
||||
|
||||
if (!m_bgViewerController)
|
||||
{
|
||||
auto ts = getOrCreateBgViewer(true);
|
||||
if (ts.get()->currentDdsConnParams() == m_session->connParams() || ts.get()->currentDdsConnParams().exerciseId == -1)
|
||||
m_bgViewerController = ts;
|
||||
}
|
||||
|
||||
emit signalInitDone();
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
if (m_session->partitionType() == IDL::PartitionType::Global)
|
||||
return false;
|
||||
|
||||
DEBUG_LOG(m_logger) << std::hex << this << " BgViewer fetchInterfaces";
|
||||
|
||||
// if (!m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc))
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Fetching 'm_ismDtc' failed!";
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (!m_session->getFtc<InfrastructureManagement::DataInterface>(m_ismFtc))
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Fetching 'm_ismFtc' failed!";
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (!m_session->getDtc<Buildings::DataInterface>(m_bldDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching 'm_bldDtc' failed!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getFtc<Buildings::DataInterface>(m_bldFtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching 'm_bldFtc' failed!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_pluginProvider)
|
||||
m_pluginProvider = new BdvPluginProvider(m_session, this);
|
||||
if (!m_pluginProvider->init())
|
||||
{
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = nullptr;
|
||||
}
|
||||
return m_pluginProvider != nullptr;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::clearInterfaces()
|
||||
{
|
||||
if (m_bgViewerController && m_bgViewerController->activeSession() == m_pluginProvider)
|
||||
m_bgViewerController->clearInterfaces(m_session->connParams());
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = nullptr;
|
||||
|
||||
// why?
|
||||
if (m_session->partitionType() == IDL::PartitionType::Global || !m_iamTheApp)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << std::hex << this << " clearInterfaces";
|
||||
|
||||
//m_ismDtc = nullptr;
|
||||
//m_ismFtc = nullptr;
|
||||
m_bldDtc = nullptr;
|
||||
m_bldFtc = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called by 'BgViewerDataView' if the user selected a building from the building list and hit the "edit" button.
|
||||
*/
|
||||
BuildingViewer::BuildingEdit *InterfaceImpl::onEditBuilding(const QString &featureId)
|
||||
{
|
||||
int32_t buildingDatabaseId = BuildingViewer::featureId2DatabaseId(featureId);
|
||||
|
||||
if (buildingDatabaseId <= 0)
|
||||
{
|
||||
QString strWarning = QStringLiteral("'featureId2DatabaseId()' did not return a valid database id. Has model with featureID '") + featureId + QStringLiteral("' been loaded with the debug dialog? In this case there is no mapping for this model in the database!");
|
||||
WARNING_LOG(m_logger) << strWarning;
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
LtsWidgets::LtsMessageDialog::showMessage(m_pDialog, QStringLiteral("DEBUG:\n") + strWarning);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc) ||
|
||||
!m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc))
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("The Infrastructure Management is not available!"), tr("Cannot open Building Edit"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BuildingViewer::BuildingEdit *pBuildingEditDialog = new BuildingViewer::BuildingEdit(m_pDialog);
|
||||
pBuildingEditDialog->init(buildingDatabaseId, ismDtc, ismFtc, m_bldDtc, m_bldFtc);
|
||||
m_pDialog->addDialog(pBuildingEditDialog, menuGroup(), QLatin1String("bdvBuildingEdit") + QString::number(buildingDatabaseId), LtsWidgets::LayoutArea::eDialogTab);
|
||||
return pBuildingEditDialog;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Directly called by 'BuildingViewer::CommunicationInterface' if 'signalViewerEventRoomNameClicked' is received.
|
||||
* Does exaclty the same what 'onEditBuilding(const QString& featureId)' does. In addition, the room id causes
|
||||
* a row selection within the newly created dialog.
|
||||
*/
|
||||
void InterfaceImpl::onRoomNameClicked(const QString &featureId, const QString &strRoomId)
|
||||
{
|
||||
BuildingViewer::BuildingEdit *pBuildingEditDialog = onEditBuilding(featureId);
|
||||
|
||||
if (!pBuildingEditDialog)
|
||||
return;
|
||||
|
||||
bool convertOk = false;
|
||||
int32_t roomMountingPointId = strRoomId.toInt(&convertOk);
|
||||
|
||||
if (!convertOk)
|
||||
{
|
||||
QString strWarning = QStringLiteral("onEditBuilding: Could not convert strRoomId to int but this should be possible since the roomId is actually a mountpoint id. featureId: ") + featureId + QStringLiteral(", strRoomId: ") + strRoomId;
|
||||
WARNING_LOG(m_logger) << strWarning;
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
LtsWidgets::LtsMessageDialog::showMessage(m_pDialog, QStringLiteral("DEBUG:\n") + strWarning);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
pBuildingEditDialog->selectRoomRow(roomMountingPointId);
|
||||
}
|
||||
|
||||
void InterfaceImpl::closeAll(LtsSession::LtsSession *session)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "close all " << m_session;
|
||||
|
||||
if(!m_bgViewerController)
|
||||
return;
|
||||
|
||||
if(m_session == session && m_bgViewerController->currentDdsConnParams() == session->connParams())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "!!!! I DIE NOW MY FELLOW";
|
||||
m_bgViewerController->closeAll();
|
||||
}
|
||||
}
|
||||
|
||||
bool InterfaceImpl::takeOverBdv()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "It's me << " << m_session <<" I'll take care of it now" ;
|
||||
if (!m_bgViewerController)
|
||||
m_bgViewerController = getOrCreateBgViewer();
|
||||
connect(m_bgViewerController.get(), &BgViewerController::signalReceivedViewState, this, &InterfaceImpl::onReceivedViewState);
|
||||
if (!m_pluginProvider)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bgViewerController->excGetViewState();
|
||||
if (!m_bgViewerController->startBgViewerAppInSession(m_pluginProvider))
|
||||
return false;
|
||||
|
||||
if (!m_bgViewerController->forceInit(m_pluginProvider))
|
||||
return false;
|
||||
if (!m_viewState.isUndefined())
|
||||
m_bgViewerController->excRestoreViewState(m_viewState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowSettings(QWidget *parent)
|
||||
{
|
||||
if (!m_bgViewerController)
|
||||
return nullptr;
|
||||
BgViewerSettingsView *dialog = new BgViewerSettingsView(m_bgViewerController.get(),
|
||||
parent);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowData(QWidget *parent)
|
||||
{
|
||||
if (!m_bgViewerController)
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("The Building Viewer COntroller is not available!"), tr("Cannot open Show Data"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc))
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("The Infrastructure Management is not available!"), tr("Cannot open Show Data"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BgViewerDataViewDialog *dialog = new BgViewerDataViewDialog(parent);
|
||||
if (!dialog->init(m_bgViewerController.get(), ismDtc, true))
|
||||
{
|
||||
delete dialog;
|
||||
ERROR_LOG(m_logger) << "cannot initialize BgViewerDataViewDialog";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
connect(m_bgViewerController.get(), &BgViewerController::bgvAppIsInitialized,
|
||||
dialog, &BgViewerDataViewDialog::fetchBuildingList);
|
||||
connect(this, &InterfaceImpl::signalFetchBuildingList,
|
||||
dialog, &BgViewerDataViewDialog::fetchBuildingList);
|
||||
connect(dialog, &BgViewerDataViewDialog::signalEditBuilding,
|
||||
this, &InterfaceImpl::onEditBuilding);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowState(QWidget *parent)
|
||||
{
|
||||
if (!m_bgViewerController)
|
||||
return nullptr;
|
||||
BgViewerStateView *dialog = new BgViewerStateView(m_bgViewerController.get(), parent);
|
||||
connect(dialog, &BgViewerStateView::signalFetchBuildingList, this, &InterfaceImpl::signalFetchBuildingList);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
|
||||
LtsWidgets::PluginData plData;
|
||||
plData.menuGroup = menuGroup();
|
||||
|
||||
bool skriptEditorMode = (m_session->app() == LtsAppDescriptor::App::ScriptEditorEssentialsView);
|
||||
|
||||
if (!skriptEditorMode)
|
||||
{
|
||||
plData.menuText = tr("Global Settings");
|
||||
plData.identifier = QLatin1String("PluginDataSettings");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:show_building_configuration.svg"));
|
||||
plData.operatorRight = OperatorRights::BuildingViewerSettingsView;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowSettings(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
|
||||
plData.menuText = tr("Building List");
|
||||
plData.identifier = QLatin1String("PluginDataBuildingList");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:evaluate.svg"));
|
||||
plData.operatorRight = OperatorRights::BuildingListView;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowData(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
plData.menuText = QStringLiteral("View State (Debug)");
|
||||
plData.identifier = QLatin1String("PluginDataViewStateDebug");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:configure_buildings.svg"));
|
||||
plData.operatorRight = OperatorRights::ViewStateDebug;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowState(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (getFlags().testFlag(LtsAppDescriptor::PluginInfo::Flag::MAIN))
|
||||
{
|
||||
plData.layoutArea = LtsWidgets::LayoutArea::eMainTab;
|
||||
plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction;
|
||||
} // else (as dialog) = rather unlikely..
|
||||
|
||||
plData.menuText = tr("Show Building Viewer");
|
||||
plData.identifier = QLatin1String("bdvShowBdv");
|
||||
plData.operatorRight = OperatorRights::BuildingViewerShow;
|
||||
plData.createWidgetFunc = [this](QWidget *)
|
||||
{
|
||||
return onShowBuildingViewerDialog();
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<BgViewerController> InterfaceImpl::getOrCreateBgViewer(bool bCreateIfNotExists)
|
||||
{
|
||||
static std::weak_ptr<BgViewerController> s_singleton;
|
||||
auto sp = s_singleton.lock();
|
||||
if (!sp)
|
||||
{
|
||||
if (!bCreateIfNotExists)
|
||||
return {};
|
||||
sp = std::make_shared<BgViewerController>(); // no parent!
|
||||
s_singleton = sp;
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowBuildingViewerDialog()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << this << ", onShowBuildingViewerDialog()";
|
||||
// Building edit dialog should also be displayed if the user clicks on a room name and the appropriate dialog has not been opened so far.
|
||||
|
||||
if (!m_bgViewerController)
|
||||
m_bgViewerController = getOrCreateBgViewer();
|
||||
|
||||
if (!m_bgViewerController->init(m_pluginProvider, true))
|
||||
return nullptr;
|
||||
|
||||
// NOTE: do not set dependency here, as onShowBuildingViewerDialog is always called from within the building viewer app's session itself
|
||||
|
||||
m_pDialog = new BuildingViewerLtsDialog;
|
||||
m_pLayout = new QVBoxLayout(m_pDialog);
|
||||
m_pLayout->addWidget(m_bgViewerController->getBgViewerWidget());
|
||||
|
||||
connect(m_bgViewerController.get(), &BgViewerController::signalViewerEventRoomNameClicked,
|
||||
this, &InterfaceImpl::onRoomNameClicked);
|
||||
|
||||
m_iamTheApp = true;
|
||||
return m_pDialog;
|
||||
}
|
||||
|
||||
//void InterfaceImpl::setBgViewerSessionDependency(/*LtsSession::LtsSession *parentSession*/) // prevents mmm to let a secondary widget be placed above this app => jetzt doch: GUEZE-2619
|
||||
//{
|
||||
// // prevent mmm from replacing
|
||||
// auto app = m_bgViewerController->app();
|
||||
// if (app)
|
||||
// {
|
||||
// LtsSession::LtsSession *session = app->getSession(m_pluginProvider->connParams().partitionType, m_pluginProvider->connParams().partitionId);
|
||||
// if (session)
|
||||
// {
|
||||
// session->setDependency(m_session);
|
||||
// /*DEBUG_*/ERROR_LOG(m_logger) << "session " << session << " now has dependency to parent session " << m_session;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "failed to set dependency for bgv app (session unavailable)";
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "failed to set dependency for bgv app (app unavailable)";
|
||||
// }
|
||||
//}
|
||||
|
||||
bool InterfaceImpl::showBuildingViewer(LtsSession::LtsSession *parentSession, int buildingId)
|
||||
{
|
||||
Q_UNUSED(parentSession);
|
||||
DEBUG_LOG(m_logger) << "showBuildingViewer (" << m_bgViewerController << ") - starting";
|
||||
|
||||
DEBUG_LOG(m_logger) << this << ", showBuildingViewer (" << buildingId << ")";
|
||||
if (!m_bgViewerController)
|
||||
m_bgViewerController = getOrCreateBgViewer();
|
||||
bool needStart = !m_bgViewerController->isBgViewerApplicationRunning();
|
||||
|
||||
if (!m_pluginProvider || m_pluginProvider->connParams() != m_bgViewerController->currentDdsConnParams())
|
||||
{
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = new BdvPluginProvider(m_session, this);
|
||||
if (!m_pluginProvider->init())
|
||||
{
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = nullptr;
|
||||
return false;
|
||||
}
|
||||
needStart = true;
|
||||
}
|
||||
if (needStart)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "showBuildingViewer (" << buildingId << ") - starting";
|
||||
if (!m_bgViewerController->startBgViewerAppInSession(m_pluginProvider))
|
||||
return false;
|
||||
|
||||
if (!m_bgViewerController->init(m_pluginProvider))
|
||||
return false;
|
||||
}
|
||||
|
||||
// setBgViewerSessionDependency(/*parentSession*/);
|
||||
|
||||
if (buildingId > 0)
|
||||
{
|
||||
m_buildingId= buildingId;
|
||||
int time = needStart ? 3000 : 500;
|
||||
QTimer::singleShot(time, this , [this]()
|
||||
{
|
||||
m_bgViewerController->openBuilding(BuildingViewer::databaseId2FeatureId(m_buildingId));
|
||||
m_buildingId=0;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
// Script Editor Topic Editor:
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
bool InterfaceImpl::initTopicEditor()
|
||||
{
|
||||
if (!m_pluginProvider)
|
||||
m_pluginProvider = new BdvPluginProvider(m_session, this);
|
||||
if (!m_pluginProvider->init())
|
||||
{
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't start BG here when we are NOT in replay!
|
||||
// the EssentialsView will start the right one no worries
|
||||
|
||||
if (m_pluginProvider->isReplayPartition())
|
||||
{
|
||||
m_bgViewerController = getOrCreateBgViewer(/*false*/); // no create since we won't/can't do an init here
|
||||
|
||||
if(!m_bgViewerController->forceInit(m_pluginProvider))
|
||||
return false;
|
||||
|
||||
if (!m_bgViewerController->init(m_pluginProvider, true))
|
||||
return false;
|
||||
|
||||
// setBgViewerSessionDependency(/*m_session*/);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::finishTopicEditor()
|
||||
{
|
||||
if (m_bgViewerController)
|
||||
m_bgViewerController->clearInterfaces(m_session->connParams());
|
||||
}
|
||||
|
||||
|
||||
TopicEditorBase::TopicEditor *InterfaceImpl::createTopicEditor(const TopicEditorBase::TopicData &data)
|
||||
{
|
||||
if (!m_bgViewerController)
|
||||
m_bgViewerController = getOrCreateBgViewer(false); // no create since we won't/can't do an init here
|
||||
|
||||
PluginProvider *session = m_bgViewerController ? m_bgViewerController->activeSession() : nullptr;
|
||||
|
||||
if (session == nullptr)
|
||||
{
|
||||
ERROR_LOG(m_logger) << this << ", bgv controller has no active session";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc = session->ismDtc();
|
||||
if (!ismDtc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "cannot fetch ism dtc from bgv controller's active session";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
BgViewerDataView *pBgvDataView = new BgViewerDataView;
|
||||
if (!pBgvDataView->init(m_bgViewerController.get(), ismDtc, false))
|
||||
{
|
||||
delete pBgvDataView;
|
||||
ERROR_LOG(m_logger) << "cannot initialize BgViewerDataView";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BuildingViewer::TopicEditor *editor = new BuildingViewer::TopicEditor(m_session, m_bgViewerController.get(), pBgvDataView);
|
||||
editor->setTopicData(data);
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
TopicReplay::Interface *InterfaceImpl::createInterface(TopicEditorBase::TopicType)
|
||||
{
|
||||
if (!initTopicEditor() || !m_bgViewerController)
|
||||
return nullptr;
|
||||
return new TopicReplayInterface(m_bgViewerController.get(), m_session);
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2017-05-15
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <BuildingViewer/bdv_viewer_gui_plugin_interface.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <Plugins/Buildings/bld_data_plugin_interface.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <Common/logger.h>
|
||||
#include "TopicEditor/topic_editor.h"
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
class QVBoxLayout;
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BuildingEdit;
|
||||
class BgViewerController;
|
||||
class BdvPluginProvider;
|
||||
|
||||
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:bdv")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override
|
||||
{
|
||||
return QLatin1String("BuildingViewerGuiPlugin");
|
||||
}
|
||||
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return (partition == IDL::PartitionType::Exercise ||
|
||||
partition == IDL::PartitionType::Replay);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Main widget of the BuildingViewer-Plugin.
|
||||
* Used by InterfaceImpl::onShowBuildingViewerDialog
|
||||
*/
|
||||
class BuildingViewerLtsDialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BuildingViewerLtsDialog()
|
||||
: LtsWidgets::LtsDialog(nullptr, LtsWidgets::ButtonCombination::SeamlessDialog, false)
|
||||
{
|
||||
setUnchangeable(true);
|
||||
}
|
||||
|
||||
void aboutToClose() override
|
||||
{
|
||||
emit signalHideLiveVideo();
|
||||
}
|
||||
|
||||
signals:
|
||||
void signalHideLiveVideo();
|
||||
|
||||
private:
|
||||
void retranslate() override
|
||||
{
|
||||
// lupdate doesn't like translate(tr("foo")) ...
|
||||
const QString txt(tr("Building Viewer"));
|
||||
translate(txt);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface, public BuildingViewer::ForeignGuiInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
QString menuGroup() const override
|
||||
{
|
||||
return tr("Building Viewer");
|
||||
}
|
||||
|
||||
void init() override;
|
||||
bool fetchInterfaces() override;
|
||||
void clearInterfaces() override;
|
||||
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return (partition == IDL::PartitionType::Exercise ||
|
||||
partition == IDL::PartitionType::Replay);
|
||||
}
|
||||
|
||||
bool showBuildingViewer(LtsSession::LtsSession *parentSession, int buildingId = 0) override;
|
||||
|
||||
// Script Editor Topic Editor:
|
||||
bool initTopicEditor() override;
|
||||
void finishTopicEditor() override;
|
||||
TopicEditorBase::TopicEditor *createTopicEditor(const TopicEditorBase::TopicData &data) override;
|
||||
|
||||
signals:
|
||||
void signalFetchBuildingList();
|
||||
void signalInitDone();
|
||||
|
||||
private slots:
|
||||
BuildingViewer::BuildingEdit* onEditBuilding(const QString& featureId);
|
||||
void onRoomNameClicked(const QString& featureId, const QString &strRoomId);
|
||||
void closeAll(LtsSession::LtsSession *session);
|
||||
bool takeOverBdv();
|
||||
void onReceivedViewState(const QJsonValue &state) {m_viewState = state;}
|
||||
|
||||
private:
|
||||
LtsWidgets::LtsDialog *onShowBuildingViewerDialog();
|
||||
static std::shared_ptr<BgViewerController> getOrCreateBgViewer(bool bCreateIfNotExists = true);
|
||||
// void setBgViewerSessionDependency(/*LtsSession::LtsSession *parentSession*/);
|
||||
|
||||
QJsonValue m_viewState;
|
||||
/*
|
||||
* 'InterfaceImpl::init()' is blocking the whole session/application.
|
||||
* This timer emits 'slotPluginInitDone' in case the BuildingViewer
|
||||
* initialization failed
|
||||
*/
|
||||
QTimer m_timerInitSaver;
|
||||
|
||||
LtsWidgets::LtsDialog *onShowSettings(QWidget *parent);
|
||||
LtsWidgets::LtsDialog *onShowData(QWidget *parent);
|
||||
LtsWidgets::LtsDialog *onShowState(QWidget *parent);
|
||||
|
||||
//std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
//std::shared_ptr<InfrastructureManagement::Interface::Ftc> m_ismFtc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
std::shared_ptr<Buildings::Interface::Ftc> m_bldFtc;
|
||||
|
||||
LtsWidgets::LtsDialog *m_pDialog = nullptr;
|
||||
QVBoxLayout *m_pLayout = nullptr;
|
||||
BdvPluginProvider *m_pluginProvider = nullptr;
|
||||
std::shared_ptr<BgViewerController> m_bgViewerController;
|
||||
int m_buildingId = 0;
|
||||
bool m_iamTheApp = false;
|
||||
|
||||
TopicReplay::Interface *createInterface(TopicEditorBase::TopicType) override;
|
||||
};
|
||||
|
||||
} // namespace BuildingViewer
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin Provider for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Christian Ehrlicher , NLE, 2020-03-18
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_gui_plugin_provider.h"
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <AdvancedSymbology/asb_data_plugin_interface.h>
|
||||
#include <AreaEffectSimulation/aes_data_plugin_interface.h>
|
||||
#include <AudioVideoManagement/avm_data_plugin_interface.h>
|
||||
#include <Buildings/bld_data_plugin_interface.h>
|
||||
#include <Buildings/bld_info_gui_plugin_interface.h>
|
||||
#include <InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <SituationReplay/srp_data_plugin_interface.h>
|
||||
#include <ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <ProjectDataManagement/pdm_data_plugin_interface.h>
|
||||
#include <ParticipantManagement/ppm_participant_info_gui_plugin_interface.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
BdvPluginProvider::BdvPluginProvider(LtsSession::LtsSession *session, QObject *parent)
|
||||
: PluginProvider(parent)
|
||||
, m_session(session)
|
||||
, m_logger(getLogger("BdvPluginProvider"))
|
||||
{}
|
||||
|
||||
bool BdvPluginProvider::init()
|
||||
{
|
||||
m_session->getForeignDataInterface<AdvancedSymbology::DataInterface>(m_asbIfc); // optional
|
||||
m_session->getDtc<SituationReplay::DataInterface>(m_srpDtc); // optionalb
|
||||
m_session->getDtc<ProjectDataManagement::DataInterface>(m_pdmDtc); // optionalb
|
||||
m_session->getDtc<AreaEffectSimulation::DataInterface>(m_aesDtc); // optionalb
|
||||
|
||||
m_session->getForeignDataInterface_NEW<AudioVideoManagement::DataInterface>(m_avmDataIfc); //optional
|
||||
|
||||
|
||||
if (!m_session->getDtc<Buildings::DataInterface>(m_bldDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching 'm_bldDtc' failed!";
|
||||
return false;
|
||||
}
|
||||
m_session->getForeignGuiInterface<Buildings::ForeignInfoGuiInterface>(m_bldInfoIfc); // optional
|
||||
// if (!m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc))
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Fetching 'm_ismDtc' failed!";
|
||||
// return false;
|
||||
// }
|
||||
// if (!m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(m_ismDataIfc))
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Fetching 'm_ismDataIfc' failed!";
|
||||
// return false;
|
||||
// }
|
||||
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching 'm_ppmDtc' failed!";
|
||||
return false;
|
||||
}
|
||||
m_session->getForeignGuiInterface<ParticipantManagement::ForeignParticipantInfoGuiInterface>(m_ppmParticipantInfoIfc); // optional
|
||||
return true;
|
||||
}
|
||||
|
||||
QString BdvPluginProvider::toString() const
|
||||
{
|
||||
return m_session ? m_session->toString() : QStringLiteral("????");
|
||||
}
|
||||
|
||||
LtsSession::DdsConnectionParams BdvPluginProvider::connParams() const
|
||||
{
|
||||
return m_session ? m_session->connParams() : LtsSession::DdsConnectionParams();
|
||||
}
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> BdvPluginProvider::ismDataIfc() const
|
||||
{
|
||||
if (!m_ismDataIfc)
|
||||
m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(m_ismDataIfc);
|
||||
|
||||
return m_ismDataIfc;
|
||||
}
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> BdvPluginProvider::ismDtc() const
|
||||
{
|
||||
if (!m_ismDtc)
|
||||
m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc);
|
||||
|
||||
return m_ismDtc;
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin Provider for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Christian Ehrlicher , NLE, 2020-03-18
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Common/bdv_plugin_provider.h>
|
||||
#include <Common/logger.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
class BdvPluginProvider : public PluginProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BdvPluginProvider(LtsSession::LtsSession *session, QObject *parent = nullptr);
|
||||
|
||||
bool init();
|
||||
|
||||
QString toString() const override;
|
||||
|
||||
int exerciseId() const override { return m_session ? m_session->exerciseId() : -1; }
|
||||
qint64 partitionTime() const override { return m_session ? m_session->partitionTime() : 0; }
|
||||
bool isReplayPartition() const override { return m_session ? m_session->isReplayPartition() : false; }
|
||||
bool isVisibleParty(int partyId) const override { return LtsSessionData::LtsSessionData::getInstance()->isVisibleParty(exerciseId(), partyId); }
|
||||
quintptr adr() const override {return (quintptr)m_session;}
|
||||
|
||||
LtsSession::DdsConnectionParams connParams() const override;
|
||||
|
||||
std::shared_ptr<AdvancedSymbology::ForeignDataInterface> asbIfc() const override { return m_asbIfc; }
|
||||
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> avmDataIfc() const override { return m_avmDataIfc; }
|
||||
std::shared_ptr<Buildings::Interface::Dtc> bldDtc() const override { return m_bldDtc; }
|
||||
std::shared_ptr<Buildings::ForeignInfoGuiInterface> bldInfoIfc() const override { return m_bldInfoIfc; }
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc() const override;
|
||||
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismDataIfc() const override;
|
||||
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> aesDtc() const override { return m_aesDtc; }
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> ppmDtc() const override { return m_ppmDtc; }
|
||||
std::shared_ptr<ProjectDataManagement::Interface::Dtc> pdmDtc() const override { return m_pdmDtc; }
|
||||
|
||||
std::shared_ptr<SituationReplay::Interface::Dtc> srpDtc() const override { return m_srpDtc; }
|
||||
|
||||
std::shared_ptr<ParticipantManagement::ForeignParticipantInfoGuiInterface> ppmParticipantInfoIfc() const override { return m_ppmParticipantInfoIfc; }
|
||||
|
||||
//private:
|
||||
LtsSession::LtsSession *m_session;
|
||||
|
||||
private:
|
||||
std::shared_ptr<AdvancedSymbology::ForeignDataInterface> m_asbIfc; // optional
|
||||
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> m_avmDataIfc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
std::shared_ptr<Buildings::ForeignInfoGuiInterface> m_bldInfoIfc; // optional
|
||||
mutable std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
|
||||
mutable std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_ismDataIfc;
|
||||
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> m_aesDtc; // optional
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc; // optional
|
||||
std::shared_ptr<SituationReplay::Interface::Dtc> m_srpDtc; // optional
|
||||
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_pdmDtc; //optional
|
||||
std::shared_ptr<ParticipantManagement::ForeignParticipantInfoGuiInterface> m_ppmParticipantInfoIfc; // optional
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#include "ui_bdv_viewer_settings.h"
|
||||
#include "bdv_viewer_settings.h"
|
||||
#include <Common/bdv_controller.h>
|
||||
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
static QVariant getSetting(const QString &key, const QVariant &def)
|
||||
{
|
||||
return LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("BgViewer"), key, def);
|
||||
}
|
||||
|
||||
static void setSetting(const QString &key, const QVariant &val)
|
||||
{
|
||||
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("BgViewer"), key, val);
|
||||
}
|
||||
|
||||
BgViewerSettingsView::BgViewerSettingsView(BgViewerController *pBgvController,
|
||||
QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_ui(new Ui::BgViewerSettingsUI)
|
||||
, m_pBgvController(pBgvController)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
resetChangeHelper();
|
||||
|
||||
m_ui->m_pSliderGlobalTransparency->setValue(getSetting(QStringLiteral("GlobalTransparency"), 75).toInt());
|
||||
m_ui->m_pCheckBoxGlobalIsoMode->setChecked(getSetting(QStringLiteral("UseIsoMode"), false).toBool());
|
||||
m_ui->m_pCheckBoxUseDotsMode->setChecked(getSetting(QStringLiteral("UseDotsMode"), false).toBool()) ;
|
||||
m_ui->m_pSliderPlayerSymbolSize->setValue(getSetting(QStringLiteral("PlayerSymbolSize"), 20).toInt());
|
||||
m_ui->m_slider_HitlineDuration->setValue(getSetting(QStringLiteral("maxHitlineDurationTime_s"), 10).toInt());
|
||||
m_ui->m_slider_SymbolFlashing->setValue(getSetting(QStringLiteral("GearFlashTime_s"), 10).toInt());
|
||||
|
||||
connect(m_ui->m_pCheckBoxGlobalIsoMode, &QCheckBox::clicked, this, &BgViewerSettingsView::onViewModeChanged);
|
||||
connect(m_ui->m_pCheckBoxUseDotsMode, &QCheckBox::clicked, this, &BgViewerSettingsView::onPlayerDisplayModeChanged);
|
||||
connect(m_ui->m_pSliderGlobalTransparency, &QSlider::valueChanged, this, &BgViewerSettingsView::onTransparencyChanged);
|
||||
connect(m_ui->m_pSliderPlayerSymbolSize, &QSlider::valueChanged, this, &BgViewerSettingsView::onSymbolSizeChanged);
|
||||
connect(m_ui->m_slider_SymbolFlashing, &QSlider::valueChanged, this, &BgViewerSettingsView::onSymbolFireEventFlashingChanged);
|
||||
connect(m_ui->m_slider_HitlineDuration, &QSlider::valueChanged, this, &BgViewerSettingsView::onHitLineDisplayLengthChanged);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Building_Viewer-Global_Settings"));
|
||||
}
|
||||
|
||||
|
||||
BgViewerSettingsView::~BgViewerSettingsView()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Global Settings"));
|
||||
onSymbolFireEventFlashingChanged(m_ui->m_slider_SymbolFlashing->value());
|
||||
onHitLineDisplayLengthChanged(m_ui->m_slider_HitlineDuration->value());
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerSettingsView::apply()
|
||||
{
|
||||
if (m_viewModeChange)
|
||||
m_pBgvController->excSetGlobalViewMode(m_ui->m_pCheckBoxGlobalIsoMode->isChecked());
|
||||
|
||||
if (m_playerDisplayModeChange)
|
||||
m_pBgvController->excSetGlobalDotsMode(m_ui->m_pCheckBoxUseDotsMode->isChecked());
|
||||
|
||||
if (m_transparencyChange)
|
||||
m_pBgvController->excSetGlobalTransparency(static_cast<double>(m_ui->m_pSliderGlobalTransparency->value()));
|
||||
|
||||
if (m_hitlineChange)
|
||||
m_pBgvController->excSetHitlineDuration(m_ui->m_slider_HitlineDuration->value());
|
||||
|
||||
if (m_symbolSizeChange)
|
||||
m_pBgvController->updatePlayerSymbols(m_ui->m_pSliderPlayerSymbolSize->value());
|
||||
|
||||
setSetting(QStringLiteral("GlobalTransparency"), m_ui->m_pSliderGlobalTransparency->value());
|
||||
setSetting(QStringLiteral("UseIsoMode"), m_ui->m_pCheckBoxGlobalIsoMode->isChecked());
|
||||
setSetting(QStringLiteral("UseDotsMode"), m_ui->m_pCheckBoxUseDotsMode->isChecked());
|
||||
setSetting(QStringLiteral("PlayerSymbolSize"), m_ui->m_pSliderPlayerSymbolSize->value());
|
||||
setSetting(QStringLiteral("maxHitlineDurationTime_s"), m_ui->m_slider_HitlineDuration->value());
|
||||
setSetting(QStringLiteral("GearFlashTime_s"), m_ui->m_slider_SymbolFlashing->value());
|
||||
setSetting(QStringLiteral("maxGearFlashTime_s"), m_ui->m_slider_SymbolFlashing->maximum());
|
||||
|
||||
resetChangeHelper();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::resetChangeHelper()
|
||||
{
|
||||
m_transparencyChange = m_viewModeChange = m_playerDisplayModeChange = m_symbolSizeChange = m_gearFlashChange = m_hitlineChange = false;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onViewModeChanged()
|
||||
{
|
||||
m_viewModeChange = true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onPlayerDisplayModeChanged()
|
||||
{
|
||||
m_playerDisplayModeChange = true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onSymbolSizeChanged()
|
||||
{
|
||||
m_symbolSizeChange = true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onTransparencyChanged()
|
||||
{
|
||||
m_transparencyChange = true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onSymbolFireEventFlashingChanged(int val)
|
||||
{
|
||||
m_gearFlashChange = true;
|
||||
m_ui->m_label_durationSymbolFlashing->setText(tr("%1 sec").arg(val));
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onHitLineDisplayLengthChanged(int val)
|
||||
{
|
||||
m_hitlineChange = true;
|
||||
m_ui->m_label_HitlineDuration->setText(tr("%1 sec").arg(val));
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BgViewerSettingsUI;
|
||||
}
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerController;
|
||||
|
||||
class BgViewerSettingsView : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BgViewerSettingsView(BgViewerController *pBgvController,
|
||||
QWidget *parent = nullptr);
|
||||
~BgViewerSettingsView();
|
||||
|
||||
private slots:
|
||||
void onViewModeChanged();
|
||||
void onPlayerDisplayModeChanged();
|
||||
void onTransparencyChanged();
|
||||
void onSymbolSizeChanged();
|
||||
void onSymbolFireEventFlashingChanged(int val);
|
||||
void onHitLineDisplayLengthChanged(int val);
|
||||
|
||||
private:
|
||||
bool m_transparencyChange, m_viewModeChange, m_playerDisplayModeChange, m_symbolSizeChange, m_gearFlashChange, m_hitlineChange;
|
||||
void resetChangeHelper();
|
||||
|
||||
bool apply() override;
|
||||
void retranslate() override;
|
||||
|
||||
Ui::BgViewerSettingsUI *m_ui;
|
||||
|
||||
BgViewerController *m_pBgvController;
|
||||
};
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,197 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BgViewerSettingsUI</class>
|
||||
<widget class="QWidget" name="BgViewerSettingsUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>429</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">General Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="2,1">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QSlider" name="m_pSliderGlobalTransparency">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>75</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxGlobalIsoMode">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use orthographic view mode</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Player symbol size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="m_label_durationSymbolFlashing">
|
||||
<property name="text">
|
||||
<string>%1 sec</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="m_label_HitlineDuration">
|
||||
<property name="text">
|
||||
<string>%1 sec</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Symbol fire event flashing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSlider" name="m_pSliderPlayerSymbolSize">
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>45</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Transparency value:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Hit line display length:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSlider" name="m_slider_HitlineDuration">
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxUseDotsMode">
|
||||
<property name="text">
|
||||
<string>Use dots mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSlider" name="m_slider_SymbolFlashing">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>m_pSliderGlobalTransparency</tabstop>
|
||||
<tabstop>m_pCheckBoxGlobalIsoMode</tabstop>
|
||||
<tabstop>m_pCheckBoxUseDotsMode</tabstop>
|
||||
<tabstop>m_pSliderPlayerSymbolSize</tabstop>
|
||||
<tabstop>m_slider_SymbolFlashing</tabstop>
|
||||
<tabstop>m_slider_HitlineDuration</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY
|
||||
*/
|
||||
#include "ui_bdv_viewer_state.h"
|
||||
#include "bdv_viewer_state.h"
|
||||
#include <Common/bdv_controller.h>
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
#include <LtsSession/lts_session_manager.h>
|
||||
#include <PluginInterfaces/data_plugin_interface.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QKeyEvent>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "bdv_viewer_state_model.h"
|
||||
#include <BuildingViewer/share/exccommands.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerStateView::BgViewerStateView(BgViewerController *pBgViewerController, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_ui(new Ui::BgViewerStateViewUI)
|
||||
, m_pBgViewerController(pBgViewerController)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
connect(m_ui->m_pushButton_SaveCurrentState, &QPushButton::clicked,
|
||||
this, &BgViewerStateView::onSaveCurrentState);
|
||||
connect(m_ui->m_pushButton_SelectModelFolder, &QPushButton::clicked,
|
||||
this, &BgViewerStateView::onSelectModelFolder);
|
||||
connect(m_ui->m_pushButton_AddModelsFromFolder, &QPushButton::clicked,
|
||||
this, &BgViewerStateView::onAddModelsFromFolder);
|
||||
connect(m_ui->m_pushButton_Record, &QPushButton::clicked,
|
||||
this, &BgViewerStateView::onStartStopRecord);
|
||||
connect(m_pBgViewerController, &BgViewerController::signalReceivedViewState,
|
||||
this, &BgViewerStateView::onHandleReceivedViewState);
|
||||
|
||||
m_ui->widget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
m_pModel = new BgViewerStateModel(this);
|
||||
m_ui->widget->setModel(m_pModel);
|
||||
|
||||
|
||||
//m_ui->widget->setMouseTracking(true); // Not working (see also eventFilter function)
|
||||
m_ui->widget->installEventFilter(this);
|
||||
m_ui->m_lineEdit_modelPath->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("BgViewer"), QStringLiteral("pathModelData"), QStringLiteral("/shd/CTC/TOOLS/TDS/GUEZ-buildings-SPD-ive/")).toString());
|
||||
}
|
||||
|
||||
|
||||
BgViewerStateView::~BgViewerStateView()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onSelectModelFolder()
|
||||
{
|
||||
QString pathToModelFolder = QFileDialog::getExistingDirectory(this, tr("Choose Building Model Data Path"), m_ui->m_lineEdit_modelPath->text(), QFileDialog::ReadOnly | QFileDialog::ShowDirsOnly);
|
||||
|
||||
if (pathToModelFolder.size())
|
||||
{
|
||||
m_ui->m_lineEdit_modelPath->setText(pathToModelFolder);
|
||||
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("BgViewer"), QStringLiteral("pathModelData"), pathToModelFolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onAddModelsFromFolder()
|
||||
{
|
||||
m_pBgViewerController->excConnect({m_ui->m_lineEdit_modelPath->text().toStdString()});
|
||||
emit signalFetchBuildingList();
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::deleteSelectedState()
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
m_pModel->removeRow(idx.row());
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerStateView::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if (object == m_ui->widget)
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonDblClick)
|
||||
{
|
||||
restoreSelectedState(); // Not working, event never occurs
|
||||
}
|
||||
else if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *pKeyEvent = static_cast<QKeyEvent *>(event);
|
||||
|
||||
// Enter: Enter on numpad
|
||||
if (pKeyEvent->key() == Qt::Key_Return || pKeyEvent->key() == Qt::Key_Enter)
|
||||
restoreSelectedState();
|
||||
else if (pKeyEvent->key() == Qt::Key_Delete)
|
||||
deleteSelectedState();
|
||||
}
|
||||
}
|
||||
|
||||
return LtsWidgets::LtsDialog::eventFilter(object, event);
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onSaveCurrentState()
|
||||
{
|
||||
m_ui->m_pushButton_SaveCurrentState->setEnabled(false);
|
||||
m_pBgViewerController->excGetViewState();
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onStartStopRecord()
|
||||
{
|
||||
static bool isRecording = false;
|
||||
|
||||
if (!isRecording)
|
||||
{
|
||||
QString strPathToFolder = QFileDialog::getExistingDirectory(this, QStringLiteral("Open Directory"),
|
||||
QStringLiteral("/shd/CTC/TOOLS/TDS/export"),
|
||||
QFileDialog::ShowDirsOnly
|
||||
| QFileDialog::DontResolveSymlinks);
|
||||
m_pBgViewerController->excStartRecording(strPathToFolder + QLatin1Char('/'), QStringLiteral("all"));
|
||||
isRecording = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pBgViewerController->excStopRecording(QStringLiteral("all"));
|
||||
isRecording = false;
|
||||
}
|
||||
|
||||
m_ui->m_pushButton_Record->setText(isRecording ? tr("Stop Recording") : tr("Start Recording"));
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onHandleReceivedViewState(const QJsonValue &val)
|
||||
{
|
||||
// list.size() will also be 0 if there are no open ViewWidgets
|
||||
const auto arr = val.toArray();
|
||||
for (const auto &ele : arr)
|
||||
m_pModel->insertRow(ele);
|
||||
|
||||
m_ui->m_pushButton_SaveCurrentState->setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::restoreSelectedState()
|
||||
{
|
||||
if (m_pModel->rowCount())
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
m_pBgViewerController->excRestoreViewState(m_pModel->getRowData(idx.row()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("View State (Debug)"));
|
||||
}
|
||||
|
||||
|
||||
} // namespace BuildingViewer
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BgViewerStateViewUI;
|
||||
}
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerController;
|
||||
class BgViewerStateModel;
|
||||
|
||||
class BgViewerStateView : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BgViewerStateView(BgViewerController *pBgViewerController, QWidget *parent = nullptr);
|
||||
~BgViewerStateView();
|
||||
|
||||
signals:
|
||||
void signalFetchBuildingList();
|
||||
|
||||
private slots:
|
||||
void onSaveCurrentState();
|
||||
void onSelectModelFolder();
|
||||
void onAddModelsFromFolder();
|
||||
void onStartStopRecord();
|
||||
void onHandleReceivedViewState(const QJsonValue &val);
|
||||
|
||||
private:
|
||||
void deleteSelectedState();
|
||||
void restoreSelectedState();
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
void retranslate() override;
|
||||
|
||||
Ui::BgViewerStateViewUI *m_ui;
|
||||
|
||||
BgViewerStateModel *m_pModel;
|
||||
|
||||
BgViewerController *m_pBgViewerController;
|
||||
};
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BgViewerStateViewUI</class>
|
||||
<widget class="QWidget" name="BgViewerStateViewUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>962</width>
|
||||
<height>433</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pushButton_SaveCurrentState">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Current State</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_lineEdit_modelPath">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pushButton_SelectModelFolder">
|
||||
<property name="text">
|
||||
<string>Select Model Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pushButton_AddModelsFromFolder">
|
||||
<property name="text">
|
||||
<string>Add Models From Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pushButton_Record">
|
||||
<property name="text">
|
||||
<string>Start Recording</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="widget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Loaded 100 of 16245 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user