FreeCAD

Форк
0
/
SoFCSelectionContext.cpp 
286 строк · 8.8 Кб
1
/****************************************************************************
2
 *   Copyright (c) 2018 Zheng Lei (realthunder) <realthunder.dev@gmail.com> *
3
 *                                                                          *
4
 *   This file is part of the FreeCAD CAx development system.               *
5
 *                                                                          *
6
 *   This library is free software; you can redistribute it and/or          *
7
 *   modify it under the terms of the GNU Library General Public            *
8
 *   License as published by the Free Software Foundation; either           *
9
 *   version 2 of the License, or (at your option) any later version.       *
10
 *                                                                          *
11
 *   This library  is distributed in the hope that it will be useful,       *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
14
 *   GNU Library General Public License for more details.                   *
15
 *                                                                          *
16
 *   You should have received a copy of the GNU Library General Public      *
17
 *   License along with this library; see the file COPYING.LIB. If not,     *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,          *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                 *
20
 *                                                                          *
21
 ****************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
# include <boost/algorithm/string/predicate.hpp>
27
# include <Inventor/elements/SoCacheElement.h>
28
# include <Inventor/misc/SoState.h>
29
#endif
30

31
#include "SoFCSelectionContext.h"
32
#include "SoFCUnifiedSelection.h"
33

34

35
using namespace Gui;
36

37
/////////////////////////////////////////////////////////////////////////////
38

39
SoFCSelectionContext::~SoFCSelectionContext() {
40
    if(counter)
41
        *counter -= 1;
42
}
43

44
bool SoFCSelectionContext::checkGlobal(SoFCSelectionContextPtr ctx) {
45
    bool sel = false;
46
    bool hl = false;
47
    SoFCSelectionRoot::checkSelection(sel,selectionColor,hl,highlightColor);
48
    if(sel)
49
        selectionIndex.insert(-1);
50
    else if(ctx && hl) {
51
        selectionColor = ctx->selectionColor;
52
        selectionIndex = ctx->selectionIndex;
53
    }else
54
        selectionIndex.clear();
55
    if(hl)
56
        highlightAll();
57
    else if(ctx && sel) {
58
        highlightIndex = ctx->highlightIndex;
59
        highlightColor = ctx->highlightColor;
60
    }else
61
        removeHighlight();
62
    return sel||hl;
63
}
64

65
bool SoFCSelectionContext::removeIndex(int index) {
66
    auto it = selectionIndex.find(index);
67
    if(it != selectionIndex.end()) {
68
        selectionIndex.erase(it);
69
        return true;
70
    }
71
    return false;
72
}
73

74
int SoFCSelectionContext::merge(int status, SoFCSelectionContextBasePtr &output,
75
        SoFCSelectionContextBasePtr input, SoNode *)
76
{
77
    auto ctx = std::dynamic_pointer_cast<SoFCSelectionContext>(input);
78
    if(!ctx)
79
        return status;
80

81
    if(ctx->selectionIndex.empty()) {
82
        output = ctx;
83
        return -1;
84
    }
85

86
    auto ret = std::dynamic_pointer_cast<SoFCSelectionContext>(output);
87
    if(!ret) {
88
        output = ctx;
89
        return 0;
90
    }
91

92
    if(ctx->isSelectAll())
93
        return status;
94

95
    if(ret->isSelectAll()) {
96
        if(!status) {
97
            output = ret->copy();
98
            ret = std::dynamic_pointer_cast<SoFCSelectionContext>(ret);
99
            assert(ret);
100
        }
101
        ret->selectionIndex = ctx->selectionIndex;
102
        return status;
103
    }
104

105
    std::vector<int> remove;
106
    for(auto idx : ret->selectionIndex) {
107
        if(!ctx->selectionIndex.count(idx))
108
            remove.push_back(idx);
109
    }
110

111
    for(auto idx : remove) {
112
        if(!status) {
113
            status = 1;
114
            output = ret->copy();
115
            ret = std::dynamic_pointer_cast<SoFCSelectionContext>(ret);
116
            assert(ret);
117
        }
118
        ret->selectionIndex.erase(idx);
119
        if(ret->selectionIndex.empty())
120
            return -1;
121
    }
122
    return status;
123
}
124

125
/////////////////////////////////////////////////////////////////////////////////////
126

127
bool SoFCSelectionContextEx::setColors(
128
        const std::map<std::string,App::Color> &colors, const std::string &element) {
129
    std::map<int,App::Color> tmp;
130
    auto it = colors.find("");
131
    if(it!=colors.end())
132
        tmp[-1] = it->second;
133
    for(auto it=colors.lower_bound(element);it!=colors.end();++it) {
134
        if(!boost::starts_with(it->first,element))
135
            break;
136
        if(it->first.size()==element.size())
137
            tmp[-1] = it->second;
138
        else {
139
            int idx = std::atoi(it->first.c_str()+4);
140
            if(idx>0) {
141
                idx -= 1;
142
                tmp[idx] = it->second;
143
            }
144
        }
145
    }
146
    if(tmp == this->colors)
147
        return false;
148
    this->colors.swap(tmp);
149
    return true;
150
}
151

152
uint32_t SoFCSelectionContextEx::packColor(const App::Color &c, bool &hasTransparency) {
153
    float trans = std::max(trans0,c.a);
154
    if(trans>0)
155
        hasTransparency = true;
156
    return SbColor(c.r,c.g,c.b).getPackedValue(trans);
157
}
158

159
bool SoFCSelectionContextEx::applyColor(int idx, std::vector<uint32_t> &packedColors, bool &hasTransparency) {
160
    if(colors.empty())
161
        return false;
162
    auto it = colors.find(idx);
163
    if(it==colors.end()) {
164
        if(colors.begin()->first >= 0)
165
            return false;
166
        it = colors.begin();
167
    }
168
    packedColors.push_back(packColor(it->second,hasTransparency));
169
    return true;
170
}
171

172
bool SoFCSelectionContextEx::isSingleColor(uint32_t &color, bool &hasTransparency) {
173
    if(!colors.empty() && colors.begin()->first<0) {
174
        color = packColor(colors.begin()->second,hasTransparency);
175
        return colors.size()==1;
176
    }
177
    return false;
178
}
179

180
int SoFCSelectionContextEx::merge(int status, SoFCSelectionContextBasePtr &output,
181
        SoFCSelectionContextBasePtr input, SoNode *node)
182
{
183
    auto ctx = std::dynamic_pointer_cast<SoFCSelectionContextEx>(input);
184
    SoFCSelectionRoot* selectionNode = dynamic_cast<SoFCSelectionRoot*>(node);
185

186
    if(!ctx) {
187
        if(selectionNode && selectionNode->hasColorOverride()) {
188
            if(!status)
189
                status = 2;
190
            else if(status == 1)
191
                status = 3;
192
        }
193
        return status;
194
    }
195

196
    int status_copy = status;
197
    if(status==2)
198
        status_copy = 0;
199
    else if(status==3)
200
        status_copy = 1;
201
    status_copy = SoFCSelectionContext::merge(status_copy,output,input,node);
202
    if(status_copy < 0)
203
        return status_copy;
204

205
    if(status>1) {
206
        // When status>1 it means there is color override before us, all
207
        // subsequent color override will be bypassed
208
        if(status_copy==1)
209
            status = 3;
210
        else
211
            status = 2;
212
        return status;
213
    }
214

215
    status = status_copy;
216
    auto ret = std::dynamic_pointer_cast<SoFCSelectionContextEx>(output);
217
    assert(ret);
218
    for(auto &v : ctx->colors) {
219
        if(ret->colors.count(v.first))
220
            continue;
221
        if(!status) {
222
            status = 1;
223
            output = ret->copy();
224
            ret = std::dynamic_pointer_cast<SoFCSelectionContextEx>(output);
225
            assert(ret);
226
        }
227
        ret->colors.insert(v);
228
    }
229

230
    if(selectionNode && selectionNode->hasColorOverride()) {
231
        if(!status)
232
            status = 2;
233
        else if(status == 1)
234
            status = 3;
235
    }
236
    return status;
237
}
238

239
///////////////////////////////////////////////////////////////////////
240

241
SoFCSelectionCounter::SoFCSelectionCounter()
242
  : counter(std::make_shared<int>(0))
243
{}
244

245
SoFCSelectionCounter::~SoFCSelectionCounter() = default;
246

247

248
bool SoFCSelectionCounter::checkRenderCache(SoState *state) {
249
    if(*counter ||
250
       (hasSelection && Selection().hasSelection()) ||
251
       (hasPreselection && Selection().hasPreselection()))
252
    {
253
        if(SoFCSelectionRoot::getCacheMode()!=SoSeparator::OFF)
254
            SoCacheElement::invalidate(state);
255
        return false;
256
    }
257
    if(!Selection().hasPreselection())
258
        hasPreselection = false;
259
    if(!Selection().hasSelection())
260
        hasSelection = false;
261
    return true;
262
}
263

264
void SoFCSelectionCounter::checkAction(SoHighlightElementAction *hlaction) {
265
    if(hlaction->isHighlighted())
266
        hasPreselection = true;
267
}
268

269
void SoFCSelectionCounter::checkAction(SoSelectionElementAction *selaction, SoFCSelectionContextPtr ctx) {
270
    switch(selaction->getType()) {
271
    case SoSelectionElementAction::None:
272
        return;
273
    case SoSelectionElementAction::All:
274
    case SoSelectionElementAction::Append:
275
        hasSelection = true;
276
        break;
277
    default:
278
        break;
279
    }
280
    if(selaction->isSecondary()) {
281
        if(ctx && !ctx->counter) {
282
            *counter += 1;
283
            ctx->counter = counter;
284
        }
285
    }
286
}
287

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.