pgItem.cxx 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file pgItem.cxx
  10. * @author drose
  11. * @date 2002-03-13
  12. */
  13. #include "pgItem.h"
  14. #include "pgMouseWatcherParameter.h"
  15. #include "pgCullTraverser.h"
  16. #include "config_pgui.h"
  17. #include "boundingVolume.h"
  18. #include "pandaNode.h"
  19. #include "sceneGraphReducer.h"
  20. #include "throw_event.h"
  21. #include "string_utils.h"
  22. #include "nodePath.h"
  23. #include "cullTraverser.h"
  24. #include "cullTraverserData.h"
  25. #include "cullBinManager.h"
  26. #include "clipPlaneAttrib.h"
  27. #include "scissorAttrib.h"
  28. #include "dcast.h"
  29. #include "boundingSphere.h"
  30. #include "boundingBox.h"
  31. #include "config_mathutil.h"
  32. #ifdef HAVE_AUDIO
  33. #include "audioSound.h"
  34. #endif
  35. using std::string;
  36. TypeHandle PGItem::_type_handle;
  37. PT(TextNode) PGItem::_text_node;
  38. PGItem *PGItem::_focus_item = nullptr;
  39. PGItem::BackgroundFocus PGItem::_background_focus;
  40. /**
  41. * Returns true if the 2-d v1 is to the right of v2.
  42. */
  43. INLINE bool
  44. is_right(const LVector2 &v1, const LVector2 &v2) {
  45. return (v1[0] * v2[1] - v1[1] * v2[0]) > 0;
  46. }
  47. /**
  48. *
  49. */
  50. PGItem::
  51. PGItem(const string &name) :
  52. PandaNode(name),
  53. _lock(name),
  54. _notify(nullptr),
  55. _has_frame(false),
  56. _frame(0, 0, 0, 0),
  57. _region(new PGMouseWatcherRegion(this)),
  58. _state(0),
  59. _flags(0)
  60. {
  61. set_cull_callback();
  62. }
  63. /**
  64. *
  65. */
  66. PGItem::
  67. ~PGItem() {
  68. if (_notify != nullptr) {
  69. _notify->remove_item(this);
  70. _notify = nullptr;
  71. }
  72. nassertv(_region->_item == this);
  73. _region->_item = nullptr;
  74. set_background_focus(false);
  75. if (_focus_item == this) {
  76. _focus_item = nullptr;
  77. }
  78. }
  79. /**
  80. *
  81. */
  82. PGItem::
  83. PGItem(const PGItem &copy) :
  84. PandaNode(copy),
  85. _notify(nullptr),
  86. _has_frame(copy._has_frame),
  87. _frame(copy._frame),
  88. _state(copy._state),
  89. _flags(copy._flags),
  90. _region(new PGMouseWatcherRegion(this))
  91. #ifdef HAVE_AUDIO
  92. , _sounds(copy._sounds)
  93. #endif
  94. {
  95. // We give our region the same name as the region for the PGItem we're
  96. // copying--so that this PGItem will generate the same event names when the
  97. // user interacts with it.
  98. _region->set_name(copy._region->get_name());
  99. // Make a deep copy of all of the original PGItem's StateDefs.
  100. size_t num_state_defs = copy._state_defs.size();
  101. _state_defs.reserve(num_state_defs);
  102. for (size_t i = 0; i < num_state_defs; ++i) {
  103. // We cheat and cast away the const, because the frame is just a cache.
  104. // But we have to get the frame out of the source before we can safely
  105. // copy it.
  106. StateDef &old_sd = (StateDef &)(copy._state_defs[i]);
  107. old_sd._frame.remove_node();
  108. old_sd._frame_stale = true;
  109. StateDef new_sd;
  110. new_sd._root = old_sd._root.copy_to(NodePath());
  111. new_sd._frame_style = old_sd._frame_style;
  112. _state_defs.push_back(new_sd);
  113. }
  114. }
  115. /**
  116. * Returns a newly-allocated Node that is a shallow copy of this one. It will
  117. * be a different Node pointer, but its internal data may or may not be shared
  118. * with that of the original Node.
  119. */
  120. PandaNode *PGItem::
  121. make_copy() const {
  122. LightReMutexHolder holder(_lock);
  123. return new PGItem(*this);
  124. }
  125. /**
  126. * Called after the node's transform has been changed for any reason, this
  127. * just provides a hook so derived classes can do something special in this
  128. * case.
  129. */
  130. void PGItem::
  131. transform_changed() {
  132. LightReMutexHolder holder(_lock);
  133. PandaNode::transform_changed();
  134. if (_notify != nullptr) {
  135. _notify->item_transform_changed(this);
  136. }
  137. }
  138. /**
  139. * Called after the node's draw_mask has been changed for any reason, this
  140. * just provides a hook so derived classes can do something special in this
  141. * case.
  142. */
  143. void PGItem::
  144. draw_mask_changed() {
  145. LightReMutexHolder holder(_lock);
  146. PandaNode::draw_mask_changed();
  147. if (_notify != nullptr) {
  148. _notify->item_draw_mask_changed(this);
  149. }
  150. }
  151. /**
  152. * This function will be called during the cull traversal to perform any
  153. * additional operations that should be performed at cull time. This may
  154. * include additional manipulation of render state or additional
  155. * visible/invisible decisions, or any other arbitrary operation.
  156. *
  157. * Note that this function will *not* be called unless set_cull_callback() is
  158. * called in the constructor of the derived class. It is necessary to call
  159. * set_cull_callback() to indicated that we require cull_callback() to be
  160. * called.
  161. *
  162. * By the time this function is called, the node has already passed the
  163. * bounding-volume test for the viewing frustum, and the node's transform and
  164. * state have already been applied to the indicated CullTraverserData object.
  165. *
  166. * The return value is true if this node should be visible, or false if it
  167. * should be culled.
  168. */
  169. bool PGItem::
  170. cull_callback(CullTraverser *trav, CullTraverserData &data) {
  171. // We try not to hold the lock for longer than necessary.
  172. PT(PandaNode) state_def_root;
  173. bool has_frame;
  174. PGMouseWatcherRegion *region;
  175. {
  176. LightReMutexHolder holder(_lock);
  177. has_frame = _has_frame && ((_flags & F_active) != 0);
  178. region = _region;
  179. int state = _state;
  180. if (state >= 0 && (size_t)state < _state_defs.size()) {
  181. StateDef &state_def = _state_defs[state];
  182. if (!state_def._root.is_empty()) {
  183. if (state_def._frame_stale) {
  184. update_frame(state);
  185. }
  186. state_def_root = state_def._root.node();
  187. }
  188. }
  189. }
  190. if (has_frame && !data.is_this_node_hidden(trav->get_camera_mask())) {
  191. // The item has a frame, so we want to generate a region for it and update
  192. // the MouseWatcher.
  193. // We can only do this if our traverser is a PGCullTraverser (which will
  194. // be the case if this node was parented somewhere under a PGTop node).
  195. if (trav->is_exact_type(PGCullTraverser::get_class_type())) {
  196. PGCullTraverser *pg_trav;
  197. DCAST_INTO_R(pg_trav, trav, true);
  198. const LMatrix4 &transform = data.get_net_transform(trav)->get_mat();
  199. // Consider the cull bin this object is in. Since the binning affects
  200. // the render order, we want bins that render later to get higher sort
  201. // values.
  202. int bin_index = data._state->get_bin_index();
  203. int sort;
  204. CullBinManager *bin_manager = CullBinManager::get_global_ptr();
  205. CullBinManager::BinType bin_type = bin_manager->get_bin_type(bin_index);
  206. if (bin_type == CullBinManager::BT_fixed) {
  207. // If the bin is a "fixed" type bin, our local sort is based on the
  208. // fixed order.
  209. sort = data._state->get_draw_order();
  210. } else if (bin_type == CullBinManager::BT_unsorted) {
  211. // If the bin is an "unsorted" type bin, we base the local sort on the
  212. // scene graph order.
  213. sort = pg_trav->_sort_index;
  214. pg_trav->_sort_index++;
  215. } else {
  216. // Otherwise, the local sort is irrelevant.
  217. sort = 0;
  218. }
  219. // Now what order does this bin sort relative to the other bins? This
  220. // becomes the high-order part of the final sort count.
  221. int bin_sort = bin_manager->get_bin_sort(data._state->get_bin_index());
  222. // Combine the two sorts into a single int. This assumes we only need
  223. // 16 bits for each sort number, possibly an erroneous assumption. We
  224. // should really provide two separate sort values, both ints, in the
  225. // MouseWatcherRegion; but in the interest of expediency we work within
  226. // the existing interface which only provides one.
  227. sort = (bin_sort << 16) | ((sort + 0x8000) & 0xffff);
  228. const ClipPlaneAttrib *clip = nullptr;
  229. const ScissorAttrib *scissor = nullptr;
  230. data._state->get_attrib(clip);
  231. data._state->get_attrib(scissor);
  232. if (activate_region(transform, sort, clip, scissor)) {
  233. pg_trav->_top->add_region(region);
  234. }
  235. }
  236. }
  237. if (state_def_root != nullptr) {
  238. // This item has a current state definition that we should use to render
  239. // the item.
  240. CullTraverserData next_data(data, state_def_root);
  241. trav->traverse(next_data);
  242. }
  243. // Now continue to render everything else below this node.
  244. return true;
  245. }
  246. /**
  247. * Returns true if there is some value to visiting this particular node during
  248. * the cull traversal for any camera, false otherwise. This will be used to
  249. * optimize the result of get_net_draw_show_mask(), so that any subtrees that
  250. * contain only nodes for which is_renderable() is false need not be visited.
  251. */
  252. bool PGItem::
  253. is_renderable() const {
  254. return true;
  255. }
  256. /**
  257. * Called when needed to recompute the node's _internal_bound object. Nodes
  258. * that contain anything of substance should redefine this to do the right
  259. * thing.
  260. */
  261. void PGItem::
  262. compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
  263. int &internal_vertices,
  264. int pipeline_stage,
  265. Thread *current_thread) const {
  266. LightReMutexHolder holder(_lock, current_thread);
  267. int num_vertices = 0;
  268. // First, get ourselves a fresh, empty bounding volume.
  269. PT(BoundingVolume) bound;
  270. BoundingVolume::BoundsType btype = get_bounds_type();
  271. if (btype == BoundingVolume::BT_default) {
  272. btype = bounds_type;
  273. }
  274. if (btype == BoundingVolume::BT_sphere) {
  275. bound = new BoundingSphere;
  276. } else {
  277. bound = new BoundingBox;
  278. }
  279. // Now actually compute the bounding volume by putting it around all of our
  280. // states' bounding volumes.
  281. pvector<const BoundingVolume *> child_volumes;
  282. // We walk through the list of state defs indirectly, calling
  283. // get_state_def() on each one, to ensure that the frames are updated
  284. // correctly before we measure their bounding volumes.
  285. for (int i = 0; i < (int)_state_defs.size(); i++) {
  286. NodePath &root = ((PGItem *)this)->do_get_state_def(i);
  287. if (!root.is_empty()) {
  288. PandaNode *node = root.node();
  289. child_volumes.push_back(node->get_bounds(current_thread));
  290. num_vertices += node->get_nested_vertices(current_thread);
  291. }
  292. }
  293. const BoundingVolume **child_begin = &child_volumes[0];
  294. const BoundingVolume **child_end = child_begin + child_volumes.size();
  295. bound->around(child_begin, child_end);
  296. internal_bounds = bound;
  297. internal_vertices = num_vertices;
  298. }
  299. /**
  300. * The recursive implementation of prepare_scene(). Don't call this directly;
  301. * call PandaNode::prepare_scene() or NodePath::prepare_scene() instead.
  302. */
  303. void PGItem::
  304. r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
  305. GeomTransformer &transformer, Thread *current_thread) {
  306. LightReMutexHolder holder(_lock);
  307. StateDefs::iterator di;
  308. for (di = _state_defs.begin(); di != _state_defs.end(); ++di) {
  309. NodePath &root = (*di)._root;
  310. if (!root.is_empty()) {
  311. PandaNode *child = root.node();
  312. CPT(RenderState) child_state = node_state->compose(child->get_state());
  313. child->r_prepare_scene(gsg, child_state, transformer, current_thread);
  314. }
  315. }
  316. PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
  317. }
  318. /**
  319. * Transforms the contents of this node by the indicated matrix, if it means
  320. * anything to do so. For most kinds of nodes, this does nothing.
  321. */
  322. void PGItem::
  323. xform(const LMatrix4 &mat) {
  324. LightReMutexHolder holder(_lock);
  325. // Transform the frame.
  326. LPoint3 ll(_frame[0], 0.0f, _frame[2]);
  327. LPoint3 ur(_frame[1], 0.0f, _frame[3]);
  328. ll = ll * mat;
  329. ur = ur * mat;
  330. _frame.set(ll[0], ur[0], ll[2], ur[2]);
  331. // Transform the individual states and their frame styles.
  332. StateDefs::iterator di;
  333. for (di = _state_defs.begin(); di != _state_defs.end(); ++di) {
  334. NodePath &root = (*di)._root;
  335. // Apply the matrix to the previous transform.
  336. root.set_transform(root.get_transform()->compose(TransformState::make_mat(mat)));
  337. // Now flatten the transform into the subgraph.
  338. SceneGraphReducer gr;
  339. gr.apply_attribs(root.node());
  340. // Transform the frame style too.
  341. if ((*di)._frame_style.xform(mat)) {
  342. (*di)._frame_stale = true;
  343. }
  344. }
  345. mark_internal_bounds_stale();
  346. }
  347. /**
  348. * Applies the indicated scene graph transform and order as determined by the
  349. * traversal from PGTop.
  350. *
  351. * The return value is true if the region is valid, or false if it is empty or
  352. * completely clipped.
  353. */
  354. bool PGItem::
  355. activate_region(const LMatrix4 &transform, int sort,
  356. const ClipPlaneAttrib *cpa,
  357. const ScissorAttrib *sa) {
  358. using std::min;
  359. using std::max;
  360. LightReMutexHolder holder(_lock);
  361. // Transform all four vertices, and get the new bounding box. This way the
  362. // region works (mostly) even if has been rotated.
  363. LPoint3 ll = LPoint3::rfu(_frame[0], 0.0f, _frame[2]) * transform;
  364. LPoint3 lr = LPoint3::rfu(_frame[1], 0.0f, _frame[2]) * transform;
  365. LPoint3 ul = LPoint3::rfu(_frame[0], 0.0f, _frame[3]) * transform;
  366. LPoint3 ur = LPoint3::rfu(_frame[1], 0.0f, _frame[3]) * transform;
  367. LVector3 up = LVector3::up();
  368. int up_axis;
  369. if (up[1]) {
  370. up_axis = 1;
  371. }
  372. else if (up[2]) {
  373. up_axis = 2;
  374. }
  375. else {
  376. up_axis = 0;
  377. }
  378. LVector3 right = LVector3::right();
  379. int right_axis;
  380. if (right[0]) {
  381. right_axis = 0;
  382. }
  383. else if (right[2]) {
  384. right_axis = 2;
  385. }
  386. else {
  387. right_axis = 1;
  388. }
  389. LVecBase4 frame;
  390. if (cpa != nullptr && cpa->get_num_on_planes() != 0) {
  391. // Apply the clip plane(s) andor scissor region now that we are here in
  392. // world space.
  393. ClipPoints points;
  394. points.reserve(4);
  395. points.push_back(LPoint2(ll[right_axis], ll[up_axis]));
  396. points.push_back(LPoint2(lr[right_axis], lr[up_axis]));
  397. points.push_back(LPoint2(ur[right_axis], ur[up_axis]));
  398. points.push_back(LPoint2(ul[right_axis], ul[up_axis]));
  399. int num_on_planes = cpa->get_num_on_planes();
  400. for (int i = 0; i < num_on_planes; ++i) {
  401. NodePath plane_path = cpa->get_on_plane(i);
  402. LPlane plane = DCAST(PlaneNode, plane_path.node())->get_plane();
  403. plane.xform(plane_path.get_net_transform()->get_mat());
  404. // We ignore the forward axis, assuming the frame is still in the right-
  405. // up plane after being transformed. Not sure if we really need to
  406. // support general 3-D transforms on 2-D objects.
  407. clip_frame(points, plane);
  408. }
  409. if (points.empty()) {
  410. // Turns out it's completely clipped after all.
  411. return false;
  412. }
  413. ClipPoints::iterator pi;
  414. pi = points.begin();
  415. frame.set((*pi)[0], (*pi)[0], (*pi)[1], (*pi)[1]);
  416. ++pi;
  417. while (pi != points.end()) {
  418. frame[0] = min(frame[0], (*pi)[0]);
  419. frame[1] = max(frame[1], (*pi)[0]);
  420. frame[2] = min(frame[2], (*pi)[1]);
  421. frame[3] = max(frame[3], (*pi)[1]);
  422. ++pi;
  423. }
  424. } else {
  425. // Since there are no clip planes involved, just set the frame.
  426. frame.set(min(min(ll[right_axis], lr[right_axis]), min(ul[right_axis], ur[right_axis])),
  427. max(max(ll[right_axis], lr[right_axis]), max(ul[right_axis], ur[right_axis])),
  428. min(min(ll[up_axis], lr[up_axis]), min(ul[up_axis], ur[up_axis])),
  429. max(max(ll[up_axis], lr[up_axis]), max(ul[up_axis], ur[up_axis])));
  430. }
  431. if (sa != nullptr) {
  432. // Also restrict it to within the scissor region.
  433. const LVecBase4 &sf = sa->get_frame();
  434. // Expand sf from 0..1 to -1..1.
  435. frame.set(max(frame[0], sf[0] * 2.0f - 1.0f),
  436. min(frame[1], sf[1] * 2.0f - 1.0f),
  437. max(frame[2], sf[2] * 2.0f - 1.0f),
  438. min(frame[3], sf[3] * 2.0f - 1.0f));
  439. if (frame[1] <= frame[0] || frame[3] <= frame[2]) {
  440. // Completely outside the scissor region.
  441. return false;
  442. }
  443. }
  444. _region->set_frame(frame);
  445. _region->set_sort(sort);
  446. _region->set_active(true);
  447. // calculate the inverse of this transform, which is needed to go back to
  448. // the frame space.
  449. _frame_inv_xform.invert_from(transform);
  450. return true;
  451. }
  452. /**
  453. * This is a callback hook function, called whenever the mouse enters the
  454. * region. The mouse is only considered to be "entered" in one region at a
  455. * time; in the case of nested regions, it exits the outer region before
  456. * entering the inner one.
  457. */
  458. void PGItem::
  459. enter_region(const MouseWatcherParameter &param) {
  460. LightReMutexHolder holder(_lock);
  461. if (pgui_cat.is_debug()) {
  462. pgui_cat.debug()
  463. << *this << "::enter_region(" << param << ")\n";
  464. }
  465. PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
  466. string event = get_enter_event();
  467. play_sound(event);
  468. throw_event(event, EventParameter(ep));
  469. if (_notify != nullptr) {
  470. _notify->item_enter(this, param);
  471. }
  472. }
  473. /**
  474. * This is a callback hook function, called whenever the mouse exits the
  475. * region. The mouse is only considered to be "entered" in one region at a
  476. * time; in the case of nested regions, it exits the outer region before
  477. * entering the inner one.
  478. */
  479. void PGItem::
  480. exit_region(const MouseWatcherParameter &param) {
  481. LightReMutexHolder holder(_lock);
  482. if (pgui_cat.is_debug()) {
  483. pgui_cat.debug()
  484. << *this << "::exit_region(" << param << ")\n";
  485. }
  486. PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
  487. string event = get_exit_event();
  488. play_sound(event);
  489. throw_event(event, EventParameter(ep));
  490. if (_notify != nullptr) {
  491. _notify->item_exit(this, param);
  492. }
  493. // pgui_cat.info() << get_name() << "::exit()" << endl;
  494. }
  495. /**
  496. * This is a callback hook function, called whenever the mouse moves within
  497. * the boundaries of the region, even if it is also within the boundaries of a
  498. * nested region. This is different from "enter", which is only called
  499. * whenever the mouse is within only that region.
  500. */
  501. void PGItem::
  502. within_region(const MouseWatcherParameter &param) {
  503. LightReMutexHolder holder(_lock);
  504. if (pgui_cat.is_debug()) {
  505. pgui_cat.debug()
  506. << *this << "::within_region(" << param << ")\n";
  507. }
  508. PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
  509. string event = get_within_event();
  510. play_sound(event);
  511. throw_event(event, EventParameter(ep));
  512. if (_notify != nullptr) {
  513. _notify->item_within(this, param);
  514. }
  515. }
  516. /**
  517. * This is a callback hook function, called whenever the mouse moves
  518. * completely outside the boundaries of the region. See within().
  519. */
  520. void PGItem::
  521. without_region(const MouseWatcherParameter &param) {
  522. LightReMutexHolder holder(_lock);
  523. if (pgui_cat.is_debug()) {
  524. pgui_cat.debug()
  525. << *this << "::without_region(" << param << ")\n";
  526. }
  527. PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
  528. string event = get_without_event();
  529. play_sound(event);
  530. throw_event(event, EventParameter(ep));
  531. if (_notify != nullptr) {
  532. _notify->item_without(this, param);
  533. }
  534. }
  535. /**
  536. * This is a callback hook function, called whenever the widget gets the
  537. * keyboard focus.
  538. */
  539. void PGItem::
  540. focus_in() {
  541. LightReMutexHolder holder(_lock);
  542. if (pgui_cat.is_debug()) {
  543. pgui_cat.debug()
  544. << *this << "::focus_in()\n";
  545. }
  546. string event = get_focus_in_event();
  547. play_sound(event);
  548. throw_event(event);
  549. if (_notify != nullptr) {
  550. _notify->item_focus_in(this);
  551. }
  552. }
  553. /**
  554. * This is a callback hook function, called whenever the widget loses the
  555. * keyboard focus.
  556. */
  557. void PGItem::
  558. focus_out() {
  559. LightReMutexHolder holder(_lock);
  560. if (pgui_cat.is_debug()) {
  561. pgui_cat.debug()
  562. << *this << "::focus_out()\n";
  563. }
  564. string event = get_focus_out_event();
  565. play_sound(event);
  566. throw_event(event);
  567. if (_notify != nullptr) {
  568. _notify->item_focus_out(this);
  569. }
  570. }
  571. /**
  572. * This is a callback hook function, called whenever a mouse or keyboard
  573. * button is depressed while the mouse is within the region.
  574. */
  575. void PGItem::
  576. press(const MouseWatcherParameter &param, bool background) {
  577. LightReMutexHolder holder(_lock);
  578. if (pgui_cat.is_debug()) {
  579. pgui_cat.debug()
  580. << *this << "::press(" << param << ", " << background << ")\n";
  581. }
  582. if (!background) {
  583. PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
  584. string event;
  585. if (param.is_keyrepeat()) {
  586. event = get_repeat_event(param.get_button());
  587. } else {
  588. event = get_press_event(param.get_button());
  589. }
  590. play_sound(event);
  591. throw_event(event, EventParameter(ep));
  592. }
  593. if (_notify != nullptr) {
  594. _notify->item_press(this, param);
  595. }
  596. }
  597. /**
  598. * This is a callback hook function, called whenever a mouse or keyboard
  599. * button previously depressed with press() is released.
  600. */
  601. void PGItem::
  602. release(const MouseWatcherParameter &param, bool background) {
  603. LightReMutexHolder holder(_lock);
  604. if (pgui_cat.is_debug()) {
  605. pgui_cat.debug()
  606. << *this << "::release(" << param << ", " << background << ")\n";
  607. }
  608. if (!background) {
  609. PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
  610. string event = get_release_event(param.get_button());
  611. play_sound(event);
  612. throw_event(event, EventParameter(ep));
  613. }
  614. if (_notify != nullptr) {
  615. _notify->item_release(this, param);
  616. }
  617. }
  618. /**
  619. * This is a callback hook function, called whenever the user presses a key.
  620. */
  621. void PGItem::
  622. keystroke(const MouseWatcherParameter &param, bool background) {
  623. LightReMutexHolder holder(_lock);
  624. if (pgui_cat.is_debug()) {
  625. pgui_cat.debug()
  626. << *this << "::keystroke(" << param << ", " << background << ")\n";
  627. }
  628. if (!background) {
  629. PGMouseWatcherParameter *ep = new PGMouseWatcherParameter(param);
  630. string event = get_keystroke_event();
  631. play_sound(event);
  632. throw_event(event, EventParameter(ep));
  633. if (has_notify()) {
  634. get_notify()->item_keystroke(this, param);
  635. }
  636. }
  637. }
  638. /**
  639. * This is a callback hook function, called whenever the user highlights an
  640. * option in the IME window.
  641. */
  642. void PGItem::
  643. candidate(const MouseWatcherParameter &param, bool background) {
  644. LightReMutexHolder holder(_lock);
  645. if (pgui_cat.is_debug()) {
  646. pgui_cat.debug()
  647. << *this << "::candidate(" << param << ", " << background << ")\n";
  648. }
  649. // We don't throw sound events for candidate selections for now.
  650. if (!background) {
  651. if (has_notify()) {
  652. get_notify()->item_candidate(this, param);
  653. }
  654. }
  655. }
  656. /**
  657. * This is a callback hook function, called whenever a mouse is moved while
  658. * within the region.
  659. */
  660. void PGItem::
  661. move(const MouseWatcherParameter &param) {
  662. LightReMutexHolder holder(_lock);
  663. if (pgui_cat.is_debug()) {
  664. pgui_cat.debug()
  665. << *this << "::move(" << param << ")\n";
  666. }
  667. if (_notify != nullptr) {
  668. _notify->item_move(this, param);
  669. }
  670. }
  671. /**
  672. * Calls press() on all the PGItems with background focus.
  673. */
  674. void PGItem::
  675. background_press(const MouseWatcherParameter &param) {
  676. BackgroundFocus::const_iterator fi;
  677. for (fi = _background_focus.begin(); fi != _background_focus.end(); ++fi) {
  678. PGItem *item = *fi;
  679. if (!item->get_focus()) {
  680. item->press(param, true);
  681. }
  682. }
  683. }
  684. /**
  685. * Calls release() on all the PGItems with background focus.
  686. */
  687. void PGItem::
  688. background_release(const MouseWatcherParameter &param) {
  689. BackgroundFocus::const_iterator fi;
  690. for (fi = _background_focus.begin(); fi != _background_focus.end(); ++fi) {
  691. PGItem *item = *fi;
  692. if (!item->get_focus()) {
  693. item->release(param, true);
  694. }
  695. }
  696. }
  697. /**
  698. * Calls keystroke() on all the PGItems with background focus.
  699. */
  700. void PGItem::
  701. background_keystroke(const MouseWatcherParameter &param) {
  702. BackgroundFocus::const_iterator fi;
  703. for (fi = _background_focus.begin(); fi != _background_focus.end(); ++fi) {
  704. PGItem *item = *fi;
  705. if (!item->get_focus()) {
  706. item->keystroke(param, true);
  707. }
  708. }
  709. }
  710. /**
  711. * Calls candidate() on all the PGItems with background focus.
  712. */
  713. void PGItem::
  714. background_candidate(const MouseWatcherParameter &param) {
  715. BackgroundFocus::const_iterator fi;
  716. for (fi = _background_focus.begin(); fi != _background_focus.end(); ++fi) {
  717. PGItem *item = *fi;
  718. if (!item->get_focus()) {
  719. item->candidate(param, true);
  720. }
  721. }
  722. }
  723. /**
  724. * Sets whether the PGItem is active for mouse watching. This is not
  725. * necessarily related to the active/inactive appearance of the item, which is
  726. * controlled by set_state(), but it does affect whether it responds to mouse
  727. * events.
  728. */
  729. void PGItem::
  730. set_active(bool active) {
  731. LightReMutexHolder holder(_lock);
  732. if (active) {
  733. _flags |= F_active;
  734. } else {
  735. _flags &= ~F_active;
  736. // Deactivating the item automatically defocuses it too.
  737. if (get_focus()) {
  738. set_focus(false);
  739. }
  740. }
  741. }
  742. /**
  743. * Sets whether the PGItem currently has keyboard focus. This simply means
  744. * that the item may respond to keyboard events as well as to mouse events;
  745. * precisely what this means is up to the individual item.
  746. *
  747. * Only one PGItem in the world is allowed to have focus at any given time.
  748. * Setting the focus on any other item automatically disables the focus from
  749. * the previous item.
  750. */
  751. void PGItem::
  752. set_focus(bool focus) {
  753. LightReMutexHolder holder(_lock);
  754. if (focus) {
  755. if (!get_active()) {
  756. // Cannot set focus on an inactive item.
  757. return;
  758. }
  759. // Set the keyboard focus to this item.
  760. if (_focus_item != this) {
  761. if (_focus_item != nullptr) {
  762. // Clear the focus from whatever item currently has it.
  763. _focus_item->set_focus(false);
  764. }
  765. _focus_item = this;
  766. }
  767. if (!get_focus()) {
  768. focus_in();
  769. _flags |= F_focus;
  770. }
  771. } else {
  772. if (_focus_item == this) {
  773. // Remove this item from the focus.
  774. _focus_item = nullptr;
  775. }
  776. if (get_focus()) {
  777. focus_out();
  778. _flags &= ~F_focus;
  779. }
  780. }
  781. _region->set_keyboard(focus);
  782. }
  783. /**
  784. * Sets the background_focus flag for this item. When background_focus is
  785. * enabled, the item will receive keypress events even if it is not in focus;
  786. * in fact, even if it is not onscreen. Unlike normal focus, many items may
  787. * have background_focus simultaneously.
  788. */
  789. void PGItem::
  790. set_background_focus(bool focus) {
  791. LightReMutexHolder holder(_lock);
  792. if (focus != get_background_focus()) {
  793. if (focus) {
  794. // Activate background focus.
  795. _flags |= F_background_focus;
  796. bool inserted = _background_focus.insert(this).second;
  797. nassertv(inserted);
  798. } else {
  799. // Deactivate background focus.
  800. _flags &= ~F_background_focus;
  801. size_t num_erased = _background_focus.erase(this);
  802. nassertv(num_erased == 1);
  803. }
  804. }
  805. }
  806. /**
  807. * Returns one more than the highest-numbered state def that was ever assigned
  808. * to the PGItem. The complete set of state defs assigned may then be
  809. * retrieved by indexing from 0 to (get_num_state_defs() - 1).
  810. *
  811. * This is only an upper limit on the actual number of state defs, since there
  812. * may be holes in the list.
  813. */
  814. int PGItem::
  815. get_num_state_defs() const {
  816. LightReMutexHolder holder(_lock);
  817. return _state_defs.size();
  818. }
  819. /**
  820. * Returns true if get_state_def() has ever been called for the indicated
  821. * state (thus defining a render subgraph for this state index), false
  822. * otherwise.
  823. */
  824. bool PGItem::
  825. has_state_def(int state) const {
  826. LightReMutexHolder holder(_lock);
  827. if (state < 0 || state >= (int)_state_defs.size()) {
  828. return false;
  829. }
  830. return (!_state_defs[state]._root.is_empty());
  831. }
  832. /**
  833. * Resets the NodePath assigned to the indicated state to its initial default,
  834. * with only a frame representation if appropriate.
  835. */
  836. void PGItem::
  837. clear_state_def(int state) {
  838. LightReMutexHolder holder(_lock);
  839. if (state < 0 || state >= (int)_state_defs.size()) {
  840. return;
  841. }
  842. _state_defs[state]._root = NodePath();
  843. _state_defs[state]._frame = NodePath();
  844. _state_defs[state]._frame_stale = true;
  845. mark_internal_bounds_stale();
  846. }
  847. /**
  848. * Parents an instance of the bottom node of the indicated NodePath to the
  849. * indicated state index.
  850. */
  851. NodePath PGItem::
  852. instance_to_state_def(int state, const NodePath &path) {
  853. LightReMutexHolder holder(_lock);
  854. if (path.is_empty()) {
  855. // If the source is empty, quietly do nothing.
  856. return NodePath();
  857. }
  858. mark_internal_bounds_stale();
  859. return path.instance_to(do_get_state_def(state));
  860. }
  861. /**
  862. * Returns the kind of frame that will be drawn behind the item when it is in
  863. * the indicated state.
  864. */
  865. PGFrameStyle PGItem::
  866. get_frame_style(int state) {
  867. LightReMutexHolder holder(_lock);
  868. if (state < 0 || state >= (int)_state_defs.size()) {
  869. return PGFrameStyle();
  870. }
  871. return _state_defs[state]._frame_style;
  872. }
  873. /**
  874. * Changes the kind of frame that will be drawn behind the item when it is in
  875. * the indicated state.
  876. */
  877. void PGItem::
  878. set_frame_style(int state, const PGFrameStyle &style) {
  879. LightReMutexHolder holder(_lock);
  880. // Get the state def node, mainly to ensure that this state is slotted and
  881. // listed as having been defined.
  882. NodePath &root = do_get_state_def(state);
  883. nassertv(!root.is_empty());
  884. _state_defs[state]._frame_style = style;
  885. _state_defs[state]._frame_stale = true;
  886. mark_internal_bounds_stale();
  887. }
  888. #ifdef HAVE_AUDIO
  889. /**
  890. * Sets the sound that will be played whenever the indicated event occurs.
  891. */
  892. void PGItem::
  893. set_sound(const string &event, AudioSound *sound) {
  894. LightReMutexHolder holder(_lock);
  895. _sounds[event] = sound;
  896. }
  897. /**
  898. * Removes the sound associated with the indicated event.
  899. */
  900. void PGItem::
  901. clear_sound(const string &event) {
  902. LightReMutexHolder holder(_lock);
  903. _sounds.erase(event);
  904. }
  905. /**
  906. * Returns the sound associated with the indicated event, or NULL if there is
  907. * no associated sound.
  908. */
  909. AudioSound *PGItem::
  910. get_sound(const string &event) const {
  911. LightReMutexHolder holder(_lock);
  912. Sounds::const_iterator si = _sounds.find(event);
  913. if (si != _sounds.end()) {
  914. return (*si).second;
  915. }
  916. return nullptr;
  917. }
  918. /**
  919. * Returns true if there is a sound associated with the indicated event, or
  920. * false otherwise.
  921. */
  922. bool PGItem::
  923. has_sound(const string &event) const {
  924. LightReMutexHolder holder(_lock);
  925. return (_sounds.count(event) != 0);
  926. }
  927. #endif // HAVE_AUDIO
  928. /**
  929. * Returns the TextNode object that will be used by all PGItems to generate
  930. * default labels given a string. This can be loaded with the default font,
  931. * etc.
  932. */
  933. TextNode *PGItem::
  934. get_text_node() {
  935. if (_text_node == nullptr) {
  936. _text_node = new TextNode("pguiText");
  937. _text_node->set_text_color(0.0f, 0.0f, 0.0f, 1.0f);
  938. // The default TextNode is aligned to the left, for the convenience of
  939. // PGEntry.
  940. _text_node->set_align(TextNode::A_left);
  941. }
  942. return _text_node;
  943. }
  944. /**
  945. * Plays the sound associated with the indicated event, if there is one.
  946. */
  947. void PGItem::
  948. play_sound(const string &event) {
  949. #ifdef HAVE_AUDIO
  950. LightReMutexHolder holder(_lock);
  951. Sounds::const_iterator si = _sounds.find(event);
  952. if (si != _sounds.end()) {
  953. AudioSound *sound = (*si).second;
  954. sound->play();
  955. }
  956. #endif // HAVE_AUDIO
  957. }
  958. /**
  959. * The frame parameter is an in/out parameter. This function adjusts frame so
  960. * that it represents the largest part of the rectangular region passed in,
  961. * that does not overlap with the rectangular region of the indicated
  962. * obscurer. If the obscurer is NULL, or is a hidden node, it is not
  963. * considered and the frame is left unchanged.
  964. *
  965. * This is used by slider bars and scroll frames, which have to automatically
  966. * figure out how much space they have to work with after allowing space for
  967. * scroll bars and buttons.
  968. */
  969. void PGItem::
  970. reduce_region(LVecBase4 &frame, PGItem *obscurer) const {
  971. using std::min;
  972. using std::max;
  973. if (obscurer != nullptr && !obscurer->is_overall_hidden()) {
  974. LVecBase4 oframe = get_relative_frame(obscurer);
  975. // Determine the four rectangular regions on the four sides of the
  976. // obscuring region.
  977. LVecBase4 right(max(frame[0], oframe[1]), frame[1], frame[2], frame[3]);
  978. LVecBase4 left(frame[0], min(frame[1], oframe[0]), frame[2], frame[3]);
  979. LVecBase4 above(frame[0], frame[1], max(frame[2], oframe[3]), frame[3]);
  980. LVecBase4 below(frame[0], frame[1], frame[2], min(frame[3], oframe[2]));
  981. // Now choose the largest of those four.
  982. const LVecBase4 *largest = &right;
  983. PN_stdfloat largest_area = compute_area(*largest);
  984. compare_largest(largest, largest_area, &left);
  985. compare_largest(largest, largest_area, &above);
  986. compare_largest(largest, largest_area, &below);
  987. frame = *largest;
  988. }
  989. }
  990. /**
  991. * Returns the LVecBase4 frame of the indicated item, converted into this
  992. * item's coordinate space. Presumably, item is a child of this node.
  993. */
  994. LVecBase4 PGItem::
  995. get_relative_frame(PGItem *item) const {
  996. using std::min;
  997. using std::max;
  998. NodePath this_np = NodePath::any_path((PGItem *)this);
  999. NodePath item_np = this_np.find_path_to(item);
  1000. if (item_np.is_empty()) {
  1001. item_np = NodePath::any_path(item);
  1002. }
  1003. const LVecBase4 &orig_frame = item->get_frame();
  1004. LMatrix4 transform = item_np.get_mat(this_np);
  1005. // Transform the item's frame into the PGScrollFrame's coordinate space.
  1006. // Transform all four vertices, and get the new bounding box. This way the
  1007. // region works (mostly) even if has been rotated.
  1008. LPoint3 ll(orig_frame[0], 0.0f, orig_frame[2]);
  1009. LPoint3 lr(orig_frame[1], 0.0f, orig_frame[2]);
  1010. LPoint3 ul(orig_frame[0], 0.0f, orig_frame[3]);
  1011. LPoint3 ur(orig_frame[1], 0.0f, orig_frame[3]);
  1012. ll = ll * transform;
  1013. lr = lr * transform;
  1014. ul = ul * transform;
  1015. ur = ur * transform;
  1016. return LVecBase4(min(min(ll[0], lr[0]), min(ul[0], ur[0])),
  1017. max(max(ll[0], lr[0]), max(ul[0], ur[0])),
  1018. min(min(ll[2], lr[2]), min(ul[2], ur[2])),
  1019. max(max(ll[2], lr[2]), max(ul[2], ur[2])));
  1020. }
  1021. /**
  1022. * Converts from the 2-d mouse coordinates into the coordinate space of the
  1023. * item.
  1024. */
  1025. LPoint3 PGItem::
  1026. mouse_to_local(const LPoint2 &mouse_point) const {
  1027. // This is ambiguous if the PGItem has multiple instances. Why would you do
  1028. // that, anyway?
  1029. NodePath this_np((PGItem *)this);
  1030. CPT(TransformState) inv_transform = NodePath().get_transform(this_np);
  1031. return inv_transform->get_mat().xform_point(LVector3::rfu(mouse_point[0], 0, mouse_point[1]));
  1032. }
  1033. /**
  1034. * Called when the user changes the frame size.
  1035. */
  1036. void PGItem::
  1037. frame_changed() {
  1038. LightReMutexHolder holder(_lock);
  1039. mark_frames_stale();
  1040. if (_notify != nullptr) {
  1041. _notify->item_frame_changed(this);
  1042. }
  1043. }
  1044. /**
  1045. * Returns the Node that is the root of the subgraph that will be drawn when
  1046. * the PGItem is in the indicated state. The first time this is called for a
  1047. * particular state index, it may create the Node.
  1048. *
  1049. * Assumes the lock is already held.
  1050. */
  1051. NodePath &PGItem::
  1052. do_get_state_def(int state) {
  1053. slot_state_def(state);
  1054. if (_state_defs[state]._root.is_empty()) {
  1055. // Create a new node.
  1056. _state_defs[state]._root = NodePath("state_" + format_string(state));
  1057. _state_defs[state]._frame_stale = true;
  1058. }
  1059. if (_state_defs[state]._frame_stale) {
  1060. update_frame(state);
  1061. }
  1062. return _state_defs[state]._root;
  1063. }
  1064. /**
  1065. * Ensures there is a slot in the array for the given state definition.
  1066. */
  1067. void PGItem::
  1068. slot_state_def(int state) {
  1069. while (state >= (int)_state_defs.size()) {
  1070. _state_defs.push_back(StateDef());
  1071. }
  1072. }
  1073. /**
  1074. * Generates a new instance of the frame geometry for the indicated state.
  1075. */
  1076. void PGItem::
  1077. update_frame(int state) {
  1078. // First, remove the old frame geometry, if any.
  1079. if (state >= 0 && state < (int)_state_defs.size()) {
  1080. _state_defs[state]._frame.remove_node();
  1081. }
  1082. // We must turn off the stale flag first, before we call get_state_def(), to
  1083. // prevent get_state_def() from being a recursive call.
  1084. _state_defs[state]._frame_stale = false;
  1085. // Now create new frame geometry.
  1086. if (has_frame()) {
  1087. NodePath &root = do_get_state_def(state);
  1088. _state_defs[state]._frame =
  1089. _state_defs[state]._frame_style.generate_into(root, _frame);
  1090. }
  1091. }
  1092. /**
  1093. * Marks all the frames in all states stale, so that they will be regenerated
  1094. * the next time each state is requested.
  1095. */
  1096. void PGItem::
  1097. mark_frames_stale() {
  1098. StateDefs::iterator di;
  1099. for (di = _state_defs.begin(); di != _state_defs.end(); ++di) {
  1100. // Remove the old frame, if any.
  1101. (*di)._frame.remove_node();
  1102. (*di)._frame_stale = true;
  1103. }
  1104. mark_internal_bounds_stale();
  1105. }
  1106. /**
  1107. * Clips the four corners of the item's frame by the indicated clipping plane,
  1108. * and modifies the points to reflect the new set of clipped points.
  1109. *
  1110. * The return value is true if the set of points is unmodified (all points are
  1111. * behind the clip plane), or false otherwise.
  1112. */
  1113. bool PGItem::
  1114. clip_frame(ClipPoints &source_points, const LPlane &plane) const {
  1115. if (source_points.empty()) {
  1116. return true;
  1117. }
  1118. LPoint3 from3d;
  1119. LVector3 delta3d;
  1120. if (!plane.intersects_plane(from3d, delta3d, LPlane(LVector3(0, 1, 0), LPoint3::zero()))) {
  1121. // The clipping plane is parallel to the polygon. The polygon is either
  1122. // all in or all out.
  1123. if (plane.dist_to_plane(LPoint3::zero()) < 0.0) {
  1124. // A point within the polygon is behind the clipping plane: the polygon
  1125. // is all in.
  1126. return true;
  1127. }
  1128. return false;
  1129. }
  1130. // Project the line of intersection into the X-Z plane. Now we have a 2-d
  1131. // clipping line.
  1132. LPoint2 from2d(from3d[0], from3d[2]);
  1133. LVector2 delta2d(delta3d[0], delta3d[2]);
  1134. PN_stdfloat a = -delta2d[1];
  1135. PN_stdfloat b = delta2d[0];
  1136. PN_stdfloat c = from2d[0] * delta2d[1] - from2d[1] * delta2d[0];
  1137. // Now walk through the points. Any point on the left of our line gets
  1138. // removed, and the line segment clipped at the point of intersection.
  1139. // We might increase the number of vertices by as many as 1, if the plane
  1140. // clips off exactly one corner. (We might also decrease the number of
  1141. // vertices, or keep them the same number.)
  1142. ClipPoints new_points;
  1143. new_points.reserve(source_points.size() + 1);
  1144. LPoint2 last_point(source_points.back());
  1145. bool last_is_in = is_right(last_point - from2d, delta2d);
  1146. bool all_in = last_is_in;
  1147. ClipPoints::const_iterator pi;
  1148. for (pi = source_points.begin(); pi != source_points.end(); ++pi) {
  1149. LPoint2 this_point(*pi);
  1150. bool this_is_in = is_right(this_point - from2d, delta2d);
  1151. // There appears to be a compiler bug in gcc 4.0: we need to extract this
  1152. // comparison outside of the if statement.
  1153. bool crossed_over = (this_is_in != last_is_in);
  1154. if (crossed_over) {
  1155. // We have just crossed over the clipping line. Find the point of
  1156. // intersection.
  1157. LVector2 d = this_point - last_point;
  1158. PN_stdfloat denom = (a * d[0] + b * d[1]);
  1159. if (denom != 0.0) {
  1160. PN_stdfloat t = -(a * last_point[0] + b * last_point[1] + c) / denom;
  1161. LPoint2 p = last_point + t * d;
  1162. new_points.push_back(p);
  1163. last_is_in = this_is_in;
  1164. }
  1165. }
  1166. if (this_is_in) {
  1167. // We are behind the clipping line. Keep the point.
  1168. new_points.push_back(this_point);
  1169. } else {
  1170. all_in = false;
  1171. }
  1172. last_point = this_point;
  1173. }
  1174. source_points.swap(new_points);
  1175. return all_in;
  1176. }