C4MapScriptAlgoPolygon::C4MapScriptAlgoPolygon(const C4PropList *props) { // Get MAPALGO_Polygon properties C4Value vptx, vpty; props->GetProperty(P_X, &vptx); props->GetProperty(P_Y, &vpty); C4ValueArray *ptx = vptx.getArray(), *pty = vpty.getArray(); if (!ptx || !pty || ptx->GetSize() != pty->GetSize()) throw C4AulExecError("C4MapScriptAlgoPolygon: Expected two equally sized int arrays in properties \"X\" and \"Y\"."); poly.resize(ptx->GetSize()); for (int32_t i=0; i<ptx->GetSize(); ++i) { poly[i].x = ptx->GetItem(i).getInt(); poly[i].y = pty->GetItem(i).getInt(); } wdt = props->GetPropertyInt(P_Wdt); if (!wdt) wdt = 1; empty = !!props->GetPropertyInt(P_Empty); open = !!props->GetPropertyInt(P_Open); if (open && !empty) throw C4AulExecError("C4MapScriptAlgoPolygon: Only empty polygons may be open."); }
C4ValueArray * C4Effect::GetProperties() const { C4ValueArray * a = C4PropList::GetProperties(); int i; i = a->GetSize(); a->SetSize(i + 5); (*a)[i++] = C4VString(&::Strings.P[P_Name]); (*a)[i++] = C4VString(&::Strings.P[P_Priority]); (*a)[i++] = C4VString(&::Strings.P[P_Interval]); (*a)[i++] = C4VString(&::Strings.P[P_CommandTarget]); (*a)[i++] = C4VString(&::Strings.P[P_Time]); return a; }
C4MapScriptAlgoModifier::C4MapScriptAlgoModifier(const C4PropList *props, int32_t min_ops, int32_t max_ops) { // Evaluate "Op" property of all algos that take another algo or layer as an operand // Op may be a proplist or an array of proplists C4Value vops; int32_t n; C4ValueArray temp_ops; props->GetProperty(P_Op, &vops); C4ValueArray *ops = vops.getArray(); if (!ops) { C4PropList *op = vops.getPropList(); if (op) { temp_ops.SetItem(0, vops); ops = &temp_ops; n = 1; } } else { n = ops->GetSize(); } if (!ops || n<min_ops || (max_ops && n>max_ops)) throw C4AulExecError(FormatString("C4MapScriptAlgo: Expected between %d and %d operands in property \"Op\".", (int)min_ops, (int)max_ops).getData()); operands.resize(n); try { // can easily crash this by building a recursive prop list // unfortunately, protecting against that is not trivial for (int32_t i=0; i<n; ++i) { C4MapScriptAlgo *new_algo = FnParAlgo(ops->GetItem(i).getPropList()); if (!new_algo) throw C4AulExecError(FormatString("C4MapScriptAlgo: Operand %d in property \"Op\" not valid.", (int)i).getData()); operands[i] = new_algo; } } catch (...) { Clear(); throw; } }
C4ValueArray *C4FindObject::FindMany(const C4ObjectList &Objs) { // Trivial case if (IsImpossible()) return new C4ValueArray(); // Set up array C4ValueArray *pArray = new C4ValueArray(32); int32_t iSize = 0; // Search for (C4ObjectLink *pLnk = Objs.First; pLnk; pLnk = pLnk->Next) if (pLnk->Obj->Status) if (Check(pLnk->Obj)) { // Grow the array, if neccessary if (iSize >= pArray->GetSize()) pArray->SetSize(iSize * 2); // Add object (*pArray)[iSize++] = C4VObj(pLnk->Obj); } // Shrink array pArray->SetSize(iSize); // Recheck object status (may shrink array again) CheckObjectStatus(pArray); // Apply sorting if (pSort) pSort->SortObjects(pArray); return pArray; }
// return is to be freed by the caller C4ValueArray *C4FindObject::FindMany(const C4ObjectList &Objs, const C4LSectors &Sct) { // Trivial case if (IsImpossible()) return new C4ValueArray(); C4Rect *pBounds = GetBounds(); if (!pBounds) return FindMany(Objs); // Prepare for array that may be generated C4ValueArray *pArray; int32_t iSize; // Check shape lists? if (UseShapes()) { // Get area C4LArea Area(&::Objects.Sectors, *pBounds); C4LSector *pSct; C4ObjectList *pLst = Area.FirstObjectShapes(&pSct); // Check if a single-sector check is enough if (!Area.Next(pSct)) return FindMany(pSct->ObjectShapes); // Set up array pArray = new C4ValueArray(32); iSize = 0; // Create marker, search all areas uint32_t iMarker = ::Objects.GetNextMarker(); for (; pLst; pLst=Area.NextObjectShapes(pLst, &pSct)) for (C4Object *obj : *pLst) if (obj->Status) if (obj->Marker != iMarker) { obj->Marker = iMarker; if (Check(obj)) { // Grow the array, if neccessary if (iSize >= pArray->GetSize()) pArray->SetSize(iSize * 2); // Add object (*pArray)[iSize++] = C4VObj(obj); } } } else { // Set up array pArray = new C4ValueArray(32); iSize = 0; // Search C4LArea Area(&::Objects.Sectors, *pBounds); C4LSector *pSct; for (C4ObjectList *pLst=Area.FirstObjects(&pSct); pLst; pLst=Area.NextObjects(pLst, &pSct)) for (C4Object *obj : *pLst) if (obj->Status) if (Check(obj)) { // Grow the array, if neccessary if (iSize >= pArray->GetSize()) pArray->SetSize(iSize * 2); // Add object (*pArray)[iSize++] = C4VObj(obj); } } // Shrink array pArray->SetSize(iSize); // Recheck object status (may shrink array again) CheckObjectStatus(pArray); // Apply sorting if (pSort) pSort->SortObjects(pArray); return pArray; }
bool C4EditCursor::DoContextMenu(DWORD dwKeyState) { bool fObjectSelected = !!Selection.ObjectCount(); #ifdef USE_WIN32_WINDOWS POINT point; GetCursorPos(&point); HMENU hContext = GetSubMenu(hMenu,0); SetMenuItemEnable( hContext, IDM_VIEWPORT_DELETE, fObjectSelected && Console.Editing); SetMenuItemEnable( hContext, IDM_VIEWPORT_DUPLICATE, fObjectSelected && Console.Editing); SetMenuItemEnable( hContext, IDM_VIEWPORT_CONTENTS, fObjectSelected && Selection.GetObject()->Contents.ObjectCount() && Console.Editing); SetMenuItemText(hContext,IDM_VIEWPORT_DELETE,LoadResStr("IDS_MNU_DELETE")); SetMenuItemText(hContext,IDM_VIEWPORT_DUPLICATE,LoadResStr("IDS_MNU_DUPLICATE")); SetMenuItemText(hContext,IDM_VIEWPORT_CONTENTS,LoadResStr("IDS_MNU_CONTENTS")); ObjselectDelItems(); C4FindObjectAtPoint pFO(X,Y); C4ValueArray * atcursor; atcursor = pFO.FindMany(::Objects, ::Objects.Sectors); // needs freeing (single object ptr) int itemcount = atcursor->GetSize(); if(itemcount > 0) { const int maxitems = 25; // Maximum displayed objects. if you raise it, also change note with IDM_VPORTDYN_FIRST in resource.h if(itemcount > maxitems) itemcount = maxitems+1; itemsObjselect.resize(itemcount+1); // +1 for a separator itemsObjselect[0].ItemId = IDM_VPORTDYN_FIRST; itemsObjselect[0].Object = NULL; AppendMenu(hContext, MF_SEPARATOR, IDM_VPORTDYN_FIRST, NULL); int i = 1; for(std::vector<ObjselItemDt>::iterator it = itemsObjselect.begin() + 1; it != itemsObjselect.end(); ++it, ++i) { C4Object * obj = (*atcursor)[i-1].getObj(); assert(obj); it->ItemId = IDM_VPORTDYN_FIRST+i; it->Object = obj; AppendMenu(hContext, MF_STRING, it->ItemId, FormatString("%s #%i (%i/%i)", obj->GetName(), obj->Number, obj->GetX(), obj->GetY()).GetWideChar()); } if(atcursor->GetSize() > maxitems) { AppendMenu(hContext, MF_GRAYED, IDM_VPORTDYN_FIRST+maxitems+1, L"..."); itemsObjselect[maxitems+1].ItemId = IDM_VPORTDYN_FIRST+maxitems+1; itemsObjselect[maxitems+1].Object = NULL; } } delete atcursor; int32_t iItem = TrackPopupMenu( hContext, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_NONOTIFY, point.x,point.y, 0, Console.hWindow, NULL); switch (iItem) { case IDM_VIEWPORT_DELETE: Delete(); break; case IDM_VIEWPORT_DUPLICATE: Duplicate(); break; case IDM_VIEWPORT_CONTENTS: GrabContents(); break; case 0: break; default: for(std::vector<ObjselItemDt>::iterator it = itemsObjselect.begin() + 1; it != itemsObjselect.end(); ++it) if(it->ItemId == iItem) { DoContextObjsel(it->Object, (dwKeyState & MK_SHIFT) == 0); break; } break; } ObjselectDelItems(); #else #ifdef WITH_DEVELOPER_MODE gtk_widget_set_sensitive(itemDelete, fObjectSelected && Console.Editing); gtk_widget_set_sensitive(itemDuplicate, fObjectSelected && Console.Editing); gtk_widget_set_sensitive(itemGrabContents, fObjectSelected && Selection.GetObject()->Contents.ObjectCount() && Console.Editing); ObjselectDelItems(); C4FindObjectAtPoint pFO(X,Y); C4ValueArray * atcursor; atcursor = pFO.FindMany(::Objects, ::Objects.Sectors); // needs freeing int itemcount = atcursor->GetSize(); if(itemcount > 0) { itemsObjselect.resize(itemcount+1); // +1 for a separator itemsObjselect[0].MenuItem = gtk_separator_menu_item_new(); itemsObjselect[0].EditCursor = this; gtk_menu_shell_append(GTK_MENU_SHELL(menuContext), itemsObjselect[0].MenuItem); int i = 0; for(std::vector<ObjselItemDt>::iterator it = itemsObjselect.begin() + 1; it != itemsObjselect.end(); ++it, ++i) { it->EditCursor = this; C4Object * obj = (*atcursor)[i].getObj(); assert(obj); it->Object = obj; GtkWidget * wdg = gtk_menu_item_new_with_label(FormatString("%s #%i (%i/%i)", obj->GetName(), obj->Number, obj->GetX(), obj->GetY()).getData()); it->MenuItem = wdg; gtk_menu_shell_append(GTK_MENU_SHELL(menuContext), wdg); g_signal_connect(G_OBJECT(wdg), "activate", G_CALLBACK(OnObjselect), &*it); } } delete atcursor; gtk_widget_show_all(menuContext); gtk_menu_popup(GTK_MENU(menuContext), NULL, NULL, NULL, NULL, 3, 0); #endif #endif return true; }
void C4ParticleValueProvider::Set(const C4ValueArray &fromArray) { startValue = endValue = 1.0f; valueFunction = &C4ParticleValueProvider::Const; size_t arraySize = (size_t) fromArray.GetSize(); if (arraySize < 2) return; int type = fromArray[0].getInt(); switch (type) { case C4PV_Const: if (arraySize >= 2) { SetType(C4PV_Const); SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue); } break; case C4PV_Linear: if (arraySize >= 3) { SetType(C4PV_Linear); SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue); SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::endValue); } break; case C4PV_Random: if (arraySize >= 3) { SetType(C4PV_Random); SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue); SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::endValue); if (arraySize >= 4) SetParameterValue(VAL_TYPE_INT, fromArray[3], 0, &C4ParticleValueProvider::rerollInterval); alreadyRolled = 0; } break; case C4PV_Direction: if (arraySize >= 2) { SetType(C4PV_Direction); SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue); } break; case C4PV_Step: if (arraySize >= 4) { SetType(C4PV_Step); SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue); SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::currentValue); SetParameterValue(VAL_TYPE_FLOAT, fromArray[3], &C4ParticleValueProvider::delay); SetParameterValue(VAL_TYPE_FLOAT, fromArray[4], &C4ParticleValueProvider::maxValue); if (delay == 0.f) delay = 1.f; } break; case C4PV_KeyFrames: if (arraySize >= 5) { SetType(C4PV_KeyFrames); SetParameterValue(VAL_TYPE_INT, fromArray[1], 0, &C4ParticleValueProvider::smoothing); keyFrames.resize(arraySize + 4 - 1); // 2*2 additional information floats at the beginning and ending, offset the first array item, though keyFrameCount = 0; const size_t startingOffset = 2; size_t i = startingOffset; for (; i < arraySize; ++i) { SetParameterValue(VAL_TYPE_KEYFRAMES, fromArray[(int32_t)i], 0, 0, 2 + i - startingOffset); } keyFrameCount = (i - startingOffset) / 2 + 2; startValue = keyFrames[2 + 1]; endValue = keyFrames[2 * keyFrameCount - 1]; // add two points for easier interpolation at beginning and ending keyFrames[0] = -500.f; keyFrames[1] = keyFrames[2 + 1]; keyFrames[2 * keyFrameCount - 2] = 1500.f; keyFrames[2 * keyFrameCount - 1] = keyFrames[keyFrameCount - 1 - 2]; } break; case C4PV_Sin: if (arraySize >= 3) { SetType(C4PV_Sin); // Sin(parameterValue) * maxValue + startValue SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::parameterValue); SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::maxValue); SetParameterValue(VAL_TYPE_FLOAT, fromArray[3], &C4ParticleValueProvider::startValue); } break; case C4PV_Speed: if (arraySize >= 3) { SetType(C4PV_Speed); SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::speedFactor); SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::startValue); } break; case C4PV_Wind: if (arraySize >= 3) { SetType(C4PV_Wind); SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::speedFactor); SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::startValue); } break; case C4PV_Gravity: if (arraySize >= 3) { SetType(C4PV_Gravity); SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::speedFactor); SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::startValue); } break; default: throw C4AulExecError("invalid particle value provider supplied"); break; } }