1 /*
2 * OpenClonk, http://www.openclonk.org
3 *
4 * Copyright (c) 1998-2000, Matthes Bender
5 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6 * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7 *
8 * Distributed under the terms of the ISC license; see accompanying file
9 * "COPYING" for details.
10 *
11 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12 * See accompanying file "TRADEMARK" for details.
13 *
14 * To redistribute this file separately, substitute the full license texts
15 * for the above references.
16 */
17
18 /* Basic classes for rectangles and vertex outlines */
19
20 #include "C4Include.h"
21 #include "object/C4Shape.h"
22
23 #include "control/C4Record.h"
24 #include "game/C4Physics.h"
25 #include "landscape/C4Landscape.h"
26 #include "landscape/C4Material.h"
27
AddVertex(int32_t iX,int32_t iY)28 bool C4Shape::AddVertex(int32_t iX, int32_t iY)
29 {
30 if (VtxNum>=C4D_MaxVertex) return false;
31 VtxX[VtxNum]=iX; VtxY[VtxNum]=iY;
32 VtxNum++;
33 return true;
34 }
35
Default()36 void C4Shape::Default()
37 {
38 InplaceReconstruct(this);
39 }
40
Rotate(C4Real Angle,bool bUpdateVertices)41 void C4Shape::Rotate(C4Real Angle, bool bUpdateVertices)
42 {
43 C4RCRotVtx rc;
44 int32_t i = 0;
45 if (Config.General.DebugRec)
46 {
47 rc.x=x; rc.y=y; rc.wdt=Wdt; rc.hgt=Hgt; rc.r=fixtoi(Angle);
48 for (; i<4; ++i)
49 { rc.VtxX[i]=VtxX[i]; rc.VtxY[i]=VtxY[i]; }
50 AddDbgRec(RCT_RotVtx1, &rc, sizeof(rc));
51 }
52 int32_t cnt,nvtx,nvty,nwdt,nhgt;
53
54 C4Real mtx[4];
55
56 // Calculate rotation matrix
57 mtx[0] = Cos(Angle); mtx[1] = -Sin(Angle);
58 mtx[2] = -mtx[1]; mtx[3] = mtx[0];
59
60 if (bUpdateVertices)
61 {
62 // Rotate vertices
63 for (cnt = 0; cnt < VtxNum; cnt++)
64 {
65 nvtx = fixtoi(mtx[0] * VtxX[cnt] + mtx[1] * VtxY[cnt]);
66 nvty = fixtoi(mtx[2] * VtxX[cnt] + mtx[3] * VtxY[cnt]);
67 VtxX[cnt] = nvtx; VtxY[cnt] = nvty;
68 }
69 }
70
71 // Enlarge Rect
72 nvtx = fixtoi(mtx[0] * x + mtx[1] * y);
73 nvty = fixtoi(mtx[2] * x + mtx[3] * y);
74 if (mtx[0] > 0)
75 {
76 if (mtx[1] > 0)
77 {
78 nwdt = fixtoi(mtx[0] * Wdt + mtx[1] * Hgt);
79 nhgt = fixtoi(mtx[1] * Wdt + mtx[0] * Hgt);
80 x = nvtx;
81 y = nvty - fixtoi(mtx[1] * Wdt);
82 }
83 else
84 {
85 nwdt = fixtoi(mtx[0] * Wdt - mtx[1] * Hgt);
86 nhgt = fixtoi(- mtx[1] * Wdt + mtx[0] * Hgt);
87 x = nvtx + fixtoi(mtx[1] * Hgt);
88 y = nvty;
89 }
90 }
91 else
92 {
93 if (mtx[1] > 0)
94 {
95 nwdt = fixtoi(- mtx[0] * Wdt + mtx[1] * Hgt);
96 nhgt = fixtoi(mtx[1] * Wdt - mtx[0] * Hgt);
97 x = nvtx + fixtoi(mtx[0] * Wdt);
98 y = nvty - nhgt;
99 }
100 else
101 {
102 nwdt = fixtoi(- mtx[0] * Wdt - mtx[1] * Hgt);
103 nhgt = fixtoi(- mtx[1] * Wdt - mtx[0] * Hgt);
104 x = nvtx - nwdt;
105 y = nvty + fixtoi(mtx[0] * Hgt);
106 }
107 }
108 Wdt = nwdt;
109 Hgt = nhgt;
110 if (Config.General.DebugRec)
111 {
112 rc.x=x; rc.y=y; rc.wdt=Wdt; rc.hgt=Hgt;
113 for (i=0; i<4; ++i)
114 { rc.VtxX[i]=VtxX[i]; rc.VtxY[i]=VtxY[i]; }
115 AddDbgRec(RCT_RotVtx2, &rc, sizeof(rc));
116 }
117 }
118
Stretch(int32_t iCon,bool bUpdateVertices)119 void C4Shape::Stretch(int32_t iCon, bool bUpdateVertices)
120 {
121 int32_t cnt;
122 x=x*iCon/FullCon;
123 y=y*iCon/FullCon;
124 Wdt=Wdt*iCon/FullCon;
125 Hgt=Hgt*iCon/FullCon;
126 if (bUpdateVertices)
127 for (cnt=0; cnt<VtxNum; cnt++)
128 {
129 VtxX[cnt]=VtxX[cnt]*iCon/FullCon;
130 VtxY[cnt]=VtxY[cnt]*iCon/FullCon;
131 }
132 }
133
Jolt(int32_t iCon,bool bUpdateVertices)134 void C4Shape::Jolt(int32_t iCon, bool bUpdateVertices)
135 {
136 int32_t cnt;
137 y=y*iCon/FullCon;
138 Hgt=Hgt*iCon/FullCon;
139 if (bUpdateVertices)
140 for (cnt=0; cnt<VtxNum; cnt++)
141 VtxY[cnt]=VtxY[cnt]*iCon/FullCon;
142 }
143
GetVertexOutline(C4Rect & rRect)144 void C4Shape::GetVertexOutline(C4Rect &rRect)
145 {
146 int32_t cnt;
147 rRect.x=rRect.y=rRect.Wdt=rRect.Hgt=0;
148 for (cnt=0; cnt<VtxNum; cnt++)
149 {
150 // Extend left
151 if (VtxX[cnt]<rRect.x)
152 {
153 rRect.Wdt+=rRect.x-VtxX[cnt];
154 rRect.x=VtxX[cnt];
155 }
156 // Extend right
157 else if (VtxX[cnt]>rRect.x+rRect.Wdt)
158 { rRect.Wdt=VtxX[cnt]-rRect.x; }
159
160 // Extend up
161 if (VtxY[cnt]<rRect.y)
162 {
163 rRect.Hgt+=rRect.y-VtxY[cnt];
164 rRect.y=VtxY[cnt];
165 }
166 // Extend down
167 else if (VtxY[cnt]>rRect.y+rRect.Hgt)
168 { rRect.Hgt=VtxY[cnt]-rRect.y; }
169 }
170
171 rRect.Hgt+=rRect.y-y;
172 rRect.y=y;
173
174 }
175
CheckTouchableMaterial(int32_t x,int32_t y,int32_t vtx_i,int32_t ydir,const C4DensityProvider & rDensityProvider)176 inline bool C4Shape::CheckTouchableMaterial(int32_t x, int32_t y, int32_t vtx_i, int32_t ydir, const C4DensityProvider &rDensityProvider) {
177 return rDensityProvider.GetDensity(x,y) >= ContactDensity &&
178 ((ydir > 0 && !(CNAT_PhaseHalfVehicle & VtxCNAT[vtx_i])) || !IsMCHalfVehicle(::Landscape.GetPix(x,y)));
179 }
180
181 // Adjust given position to one pixel before contact
182 // at vertices matching CNAT request.
Attach(int32_t & cx,int32_t & cy,BYTE cnat_pos)183 bool C4Shape::Attach(int32_t &cx, int32_t &cy, BYTE cnat_pos)
184 {
185 // reset attached material
186 AttachMat=MNone;
187 int xcd = 0;
188 int ycd = 0;
189 // determine attachment direction
190 switch (cnat_pos & (~CNAT_Flags))
191 {
192 case CNAT_Top: ycd=-1; break;
193 case CNAT_Bottom: ycd=+1; break;
194 case CNAT_Left: xcd=-1; break;
195 case CNAT_Right: xcd=+1; break;
196 default: return false;
197 }
198 int testx = cx;
199 int testy = cy;
200 bool increase_distance = true;
201 bool any_contact = false;
202 // Find the nearest position that has at least one vertex adjacent to dense material
203 // and no vertices in dense materials
204 while (Abs(testx - cx) < AttachRange && Abs(testy - cy) < AttachRange)
205 {
206 bool found = false;
207 for (int i = 0; i < VtxNum; ++i)
208 {
209 if (VtxCNAT[i] & cnat_pos)
210 {
211 // get new vertex pos
212 int32_t ax = testx + VtxX[i], ay = testy + VtxY[i];
213 if (CheckTouchableMaterial(ax, ay, i))
214 {
215 found = false;
216 break;
217 }
218 // can attach here?
219 if (CheckTouchableMaterial(ax + xcd, ay + ycd, i, ycd))
220 {
221 found = true;
222 any_contact = true;
223 // store attachment material
224 AttachMat = GBackMat(ax + xcd, ay + ycd);
225 // store absolute attachment position
226 iAttachX = ax + xcd; iAttachY = ay + ycd;
227 iAttachVtx = i;
228 }
229
230 }
231 }
232 if (found)
233 {
234 cx = testx;
235 cy = testy;
236 return true;
237 }
238 // Try positions in order of distance from the origin,
239 // and alternating the direction
240 testx = cx - (testx - cx);
241 testy = cy - (testy - cy);
242 if (increase_distance)
243 {
244 testx += xcd;
245 testy += ycd;
246 }
247 increase_distance = !increase_distance;
248 }
249 return any_contact;
250 }
251
252
LineConnect(int32_t tx,int32_t ty,int32_t cvtx,int32_t ld,int32_t oldx,int32_t oldy)253 bool C4Shape::LineConnect(int32_t tx, int32_t ty, int32_t cvtx, int32_t ld, int32_t oldx, int32_t oldy)
254 {
255
256 if (VtxNum<2) return false;
257
258 // No modification
259 if ((VtxX[cvtx]==tx) && (VtxY[cvtx]==ty)) return true;
260
261 // Check new path
262 int32_t ix,iy;
263 if (PathFree(tx,ty,VtxX[cvtx+ld],VtxY[cvtx+ld],&ix,&iy))
264 {
265 // Okay, set vertex
266 VtxX[cvtx]=tx; VtxY[cvtx]=ty;
267 return true;
268 }
269 else
270 {
271 // Intersected, find bend vertex
272 bool found = false;
273 int32_t cix;
274 int32_t ciy;
275 for (int irange = 4; irange <= 12; irange += 4)
276 for (cix = ix - irange / 2; cix <= ix + irange; cix += irange)
277 for (ciy = iy - irange / 2; ciy <= iy + irange; ciy += irange)
278 {
279 if (PathFree(cix,ciy,tx,ty) && PathFree(cix,ciy,VtxX[cvtx+ld],VtxY[cvtx+ld]))
280 {
281 found = true;
282 goto out;
283 }
284 }
285 out:
286 if (!found)
287 {
288 // try bending directly at path the line took
289 // allow going through vehicle in this case to allow lines through castles and elevator shafts
290 cix = oldx;
291 ciy = oldy;
292 if (!PathFreeIgnoreVehicle(cix,ciy,tx,ty) || !PathFreeIgnoreVehicle(cix,ciy,VtxX[cvtx+ld],VtxY[cvtx+ld]))
293 if (!PathFreeIgnoreVehicle(cix,ciy,tx,ty) || !PathFreeIgnoreVehicle(cix,ciy,VtxX[cvtx+ld],VtxY[cvtx+ld]))
294 return false; // Found no bend vertex
295 }
296 // Insert bend vertex
297 if (ld>0)
298 {
299 if (!InsertVertex(cvtx+1,cix,ciy)) return false;
300 }
301 else
302 {
303 if (!InsertVertex(cvtx,cix,ciy)) return false;
304 cvtx++;
305 }
306 // Okay, set vertex
307 VtxX[cvtx]=tx; VtxY[cvtx]=ty;
308 return true;
309 }
310
311 return false;
312 }
313
InsertVertex(int32_t iPos,int32_t tx,int32_t ty)314 bool C4Shape::InsertVertex(int32_t iPos, int32_t tx, int32_t ty)
315 {
316 if (VtxNum+1>C4D_MaxVertex) return false;
317 if (iPos < 0 || iPos > VtxNum) return false;
318 // Insert vertex before iPos
319 for (int32_t cnt=VtxNum; cnt>iPos; cnt--)
320 { VtxX[cnt]=VtxX[cnt-1]; VtxY[cnt]=VtxY[cnt-1]; }
321 VtxX[iPos]=tx; VtxY[iPos]=ty;
322 VtxNum++;
323 return true;
324 }
325
RemoveVertex(int32_t iPos)326 bool C4Shape::RemoveVertex(int32_t iPos)
327 {
328 if (!Inside<int32_t>(iPos,0,VtxNum-1)) return false;
329 for (int32_t cnt=iPos; cnt+1<VtxNum; cnt++)
330 { VtxX[cnt]=VtxX[cnt+1]; VtxY[cnt]=VtxY[cnt+1]; }
331 VtxNum--;
332 return true;
333 }
334
CheckContact(int32_t cx,int32_t cy)335 bool C4Shape::CheckContact(int32_t cx, int32_t cy)
336 {
337 // Check all vertices at given object position.
338 // Return true on any contact.
339
340
341 for (int32_t cvtx=0; cvtx<VtxNum; cvtx++)
342 if (!(VtxCNAT[cvtx] & CNAT_NoCollision))
343 if (CheckTouchableMaterial(cx+VtxX[cvtx],cy+VtxY[cvtx], cvtx))
344 return true;
345
346
347 return false;
348 }
349
ContactCheck(int32_t cx,int32_t cy,uint32_t * border_hack_contacts,bool collide_halfvehic)350 bool C4Shape::ContactCheck(int32_t cx, int32_t cy, uint32_t *border_hack_contacts, bool collide_halfvehic)
351 {
352 // Check all vertices at given object position.
353 // Set ContactCNAT and ContactCount.
354 // Set VtxContactCNAT and VtxContactMat.
355 // Return true on any contact.
356
357
358 ContactCNAT=CNAT_None;
359 ContactCount=0;
360
361 for (int32_t cvtx=0; cvtx<VtxNum; cvtx++)
362
363 // Ignore vertex if collision has been flagged out
364 if (!(VtxCNAT[cvtx] & CNAT_NoCollision))
365
366 {
367 VtxContactCNAT[cvtx]=CNAT_None;
368 int32_t x = cx+VtxX[cvtx];
369 int32_t y = cy+VtxY[cvtx];
370 VtxContactMat[cvtx]=GBackMat(x,y);
371
372 if (CheckTouchableMaterial(x, y, cvtx, collide_halfvehic? 1:0))
373 {
374 ContactCNAT |= VtxCNAT[cvtx];
375 VtxContactCNAT[cvtx]|=CNAT_Center;
376 ContactCount++;
377 // Vertex center contact, now check top,bottom,left,right
378 if (CheckTouchableMaterial(x,y-1,cvtx, collide_halfvehic ? 1 : 0))
379 VtxContactCNAT[cvtx]|=CNAT_Top;
380 if (CheckTouchableMaterial(x,y+1,cvtx, collide_halfvehic ? 1 : 0))
381 VtxContactCNAT[cvtx]|=CNAT_Bottom;
382 if (CheckTouchableMaterial(x-1,y,cvtx, collide_halfvehic ? 1 : 0))
383 VtxContactCNAT[cvtx]|=CNAT_Left;
384 if (CheckTouchableMaterial(x+1,y,cvtx, collide_halfvehic ? 1 : 0))
385 VtxContactCNAT[cvtx]|=CNAT_Right;
386 }
387 if (border_hack_contacts)
388 {
389 if (x == 0 && CheckTouchableMaterial(x-1, y, cvtx)) *border_hack_contacts |= CNAT_Left;
390 else if (x == ::Landscape.GetWidth() && CheckTouchableMaterial(x+1, y, cvtx)) *border_hack_contacts |= CNAT_Right;
391 }
392 }
393
394
395 return !!ContactCount;
396 }
397
CheckScaleToWalk(int x,int y)398 bool C4Shape::CheckScaleToWalk(int x, int y)
399 {
400 for (int32_t i = 0; i < VtxNum; i++)
401 {
402 if (VtxCNAT[i] & CNAT_NoCollision)
403 continue;
404 if (VtxCNAT[i] & CNAT_Bottom)
405 {
406 // no ground under the feet?
407 if (CheckTouchableMaterial(x + VtxX[i], y + VtxY[i] + 1, i))
408 return false;
409 }
410 else
411 {
412 // can climb with hands?
413 if (CheckTouchableMaterial(x + VtxX[i] - 1, y + VtxY[i], i))
414 return false;
415 if (CheckTouchableMaterial(x + VtxX[i] + 1, y + VtxY[i], i))
416 return false;
417 }
418 }
419 return true;
420 }
421
GetVertexX(int32_t iVertex)422 int32_t C4Shape::GetVertexX(int32_t iVertex)
423 {
424 if (!Inside<int32_t>(iVertex,0,VtxNum-1)) return 0;
425 return VtxX[iVertex];
426 }
427
GetVertexY(int32_t iVertex)428 int32_t C4Shape::GetVertexY(int32_t iVertex)
429 {
430 if (!Inside<int32_t>(iVertex,0,VtxNum-1)) return 0;
431 return VtxY[iVertex];
432 }
433
CopyFrom(C4Shape rFrom,bool bCpyVertices,bool fCopyVerticesFromSelf)434 void C4Shape::CopyFrom(C4Shape rFrom, bool bCpyVertices, bool fCopyVerticesFromSelf)
435 {
436 if (bCpyVertices)
437 {
438 // truncate / copy vertex count
439 VtxNum = (fCopyVerticesFromSelf ? std::min<int32_t>(VtxNum, C4D_VertexCpyPos) : rFrom.VtxNum);
440 // restore vertices from back of own buffer (retaining count)
441 int32_t iCopyPos = (fCopyVerticesFromSelf ? C4D_VertexCpyPos : 0);
442 C4Shape &rVtxFrom = (fCopyVerticesFromSelf ? *this : rFrom);
443 memcpy(VtxX, rVtxFrom.VtxX+iCopyPos, VtxNum*sizeof(*VtxX));
444 memcpy(VtxY, rVtxFrom.VtxY+iCopyPos, VtxNum*sizeof(*VtxY));
445 memcpy(VtxCNAT, rVtxFrom.VtxCNAT+iCopyPos, VtxNum*sizeof(*VtxCNAT));
446 memcpy(VtxFriction, rVtxFrom.VtxFriction+iCopyPos, VtxNum*sizeof(*VtxFriction));
447 memcpy(VtxContactCNAT, rVtxFrom.VtxContactCNAT+iCopyPos, VtxNum*sizeof(*VtxContactCNAT));
448 memcpy(VtxContactMat, rVtxFrom.VtxContactMat+iCopyPos, VtxNum*sizeof(*VtxContactMat));
449 // continue: copies other members
450 }
451 *((C4Rect *) this) = rFrom;
452 AttachMat=rFrom.AttachMat;
453 ContactCNAT=rFrom.ContactCNAT;
454 ContactCount=rFrom.ContactCount;
455 }
456
GetBottomVertex()457 int32_t C4Shape::GetBottomVertex()
458 {
459 // return bottom-most vertex
460 int32_t iMax = -1;
461 for (int32_t i = 0; i < VtxNum; i++)
462 if (VtxCNAT[i] & CNAT_Bottom)
463 if (iMax == -1 || VtxY[i] < VtxY[iMax])
464 iMax = i;
465 return iMax;
466 }
467
GetBottom()468 int C4Shape::GetBottom()
469 {
470 int b = INT_MIN;
471 for (int32_t i = 0; i < VtxNum; i++)
472 if (~VtxCNAT[i] & CNAT_NoCollision)
473 if (VtxY[i] > b)
474 b = VtxY[i];
475 if (b == INT_MIN)
476 return y + Hgt;
477 return b;
478 }
479
480 C4DensityProvider DefaultDensityProvider;
481
GetDensity(int32_t x,int32_t y) const482 int32_t C4DensityProvider::GetDensity(int32_t x, int32_t y) const
483 {
484 // default density provider checks the landscape
485 return GBackDensity(x,y);
486 }
487
GetVertexContact(int32_t iVtx,DWORD dwCheckMask,int32_t tx,int32_t ty,const C4DensityProvider & rDensityProvider)488 int32_t C4Shape::GetVertexContact(int32_t iVtx, DWORD dwCheckMask, int32_t tx, int32_t ty, const C4DensityProvider &rDensityProvider)
489 {
490 // default check mask
491 if (!dwCheckMask) dwCheckMask = VtxCNAT[iVtx];
492 // check vertex positions (vtx num not range-checked!)
493 tx += VtxX[iVtx]; ty += VtxY[iVtx];
494 int32_t iContact = 0;
495 // check all directions for solid mat
496 if (~VtxCNAT[iVtx] & CNAT_NoCollision)
497 {
498 if (dwCheckMask & CNAT_Center) if (CheckTouchableMaterial(tx, ty , iVtx, 0, rDensityProvider)) iContact |= CNAT_Center;
499 if (dwCheckMask & CNAT_Left) if (CheckTouchableMaterial(tx-1, ty, iVtx, 0, rDensityProvider)) iContact |= CNAT_Left;
500 if (dwCheckMask & CNAT_Right) if (CheckTouchableMaterial(tx+1, ty, iVtx, 0, rDensityProvider)) iContact |= CNAT_Right;
501 if (dwCheckMask & CNAT_Top) if (CheckTouchableMaterial(tx, ty-1, iVtx, 0, rDensityProvider)) iContact |= CNAT_Top;
502 if (dwCheckMask & CNAT_Bottom) if (CheckTouchableMaterial(tx, ty+1, iVtx, 1, rDensityProvider)) iContact |= CNAT_Bottom;
503 }
504 // return resulting bitmask
505 return iContact;
506 }
507
CreateOwnOriginalCopy(C4Shape & rFrom)508 void C4Shape::CreateOwnOriginalCopy(C4Shape &rFrom)
509 {
510 // copy vertices from original buffer, including count
511 VtxNum = std::min<int32_t>(rFrom.VtxNum, C4D_VertexCpyPos);
512 memcpy(VtxX+C4D_VertexCpyPos, rFrom.VtxX, VtxNum*sizeof(*VtxX));
513 memcpy(VtxY+C4D_VertexCpyPos, rFrom.VtxY, VtxNum*sizeof(*VtxY));
514 memcpy(VtxCNAT+C4D_VertexCpyPos, rFrom.VtxCNAT, VtxNum*sizeof(*VtxCNAT));
515 memcpy(VtxFriction+C4D_VertexCpyPos, rFrom.VtxFriction, VtxNum*sizeof(*VtxFriction));
516 memcpy(VtxContactCNAT+C4D_VertexCpyPos, rFrom.VtxContactCNAT, VtxNum*sizeof(*VtxContactCNAT));
517 memcpy(VtxContactMat+C4D_VertexCpyPos, rFrom.VtxContactMat, VtxNum*sizeof(*VtxContactMat));
518 }
519
CompileFunc(StdCompiler * pComp,const C4Shape * default_shape)520 void C4Shape::CompileFunc(StdCompiler *pComp, const C4Shape *default_shape)
521 {
522 const StdBitfieldEntry<int32_t> ContactDirections[] =
523 {
524
525 { "CNAT_None", CNAT_None },
526 { "CNAT_Left", CNAT_Left },
527 { "CNAT_Right", CNAT_Right },
528 { "CNAT_Top", CNAT_Top },
529 { "CNAT_Bottom", CNAT_Bottom },
530 { "CNAT_Center", CNAT_Center },
531 { "CNAT_MultiAttach", CNAT_MultiAttach },
532 { "CNAT_NoCollision", CNAT_NoCollision },
533 { "CNAT_PhaseHalfVehicle", CNAT_PhaseHalfVehicle },
534
535 { nullptr, 0 }
536 };
537
538 // a default shape is given in object compilation context only
539 bool fRuntime = !!default_shape;
540 C4Shape default_def_shape;
541 if (!default_shape) default_shape = &default_def_shape;
542 // Note: Compiled directly into "Object" and "DefCore"-categories, so beware of name clashes
543 // (see C4Object::CompileFunc and C4Def::CompileFunc)
544 pComp->Value(mkNamingAdapt( Wdt, "Width", default_shape->Wdt));
545 pComp->Value(mkNamingAdapt( Hgt, "Height", default_shape->Hgt));
546 pComp->Value(mkNamingAdapt( mkArrayAdaptDefArr(&x,2,&default_shape->x), "Offset", &default_shape->x));
547 pComp->Value(mkNamingAdapt( VtxNum, "Vertices", default_shape->VtxNum));
548 pComp->Value(mkNamingAdapt( mkArrayAdaptDMA(VtxX, default_shape->VtxX), "VertexX", default_shape->VtxX));
549 pComp->Value(mkNamingAdapt( mkArrayAdaptDMA(VtxY, default_shape->VtxY), "VertexY", default_shape->VtxY));
550 pComp->Value(mkNamingAdapt( mkArrayAdaptDMAM(VtxCNAT, default_shape->VtxCNAT, [&](decltype(*VtxCNAT) &elem){ return mkBitfieldAdapt<int32_t>(elem, ContactDirections); }), "VertexCNAT", default_shape->VtxCNAT));
551 pComp->Value(mkNamingAdapt( mkArrayAdaptDMA(VtxFriction, default_shape->VtxFriction), "VertexFriction", default_shape->VtxFriction));
552 pComp->Value(mkNamingAdapt( ContactDensity, "ContactDensity", default_shape->ContactDensity));
553 if (fRuntime)
554 {
555 pComp->Value(mkNamingAdapt( iAttachX, "AttachX", 0 ));
556 pComp->Value(mkNamingAdapt( iAttachY, "AttachY", 0 ));
557 pComp->Value(mkNamingAdapt( iAttachVtx, "AttachVtx", 0 ));
558 }
559 }
560