@@ -231,6 +231,50 @@ void editor::CodeEditor::updateScriptProperties(const EditorInstance& instance,
231231 }
232232}
233233
234+ std::string editor::CodeEditor::toCamelCase (const std::string& name) {
235+ std::string result;
236+ bool nextUpper = false ;
237+ for (char c : name) {
238+ if (std::isalnum (static_cast <unsigned char >(c))) {
239+ if (result.empty ()) {
240+ result += (char )std::tolower (static_cast <unsigned char >(c));
241+ } else if (nextUpper) {
242+ result += (char )std::toupper (static_cast <unsigned char >(c));
243+ nextUpper = false ;
244+ } else {
245+ result += c;
246+ }
247+ } else {
248+ if (!result.empty ()) nextUpper = true ;
249+ }
250+ }
251+ return result.empty () ? " entity" : result;
252+ }
253+
254+ std::string editor::CodeEditor::toDisplayName (const std::string& camelCase) {
255+ std::string result;
256+ for (size_t i = 0 ; i < camelCase.size (); i++) {
257+ if (i == 0 ) {
258+ result += (char )std::toupper (static_cast <unsigned char >(camelCase[i]));
259+ } else if (std::isupper (static_cast <unsigned char >(camelCase[i]))) {
260+ result += ' ' ;
261+ result += camelCase[i];
262+ } else {
263+ result += camelCase[i];
264+ }
265+ }
266+ return result;
267+ }
268+
269+ void editor::CodeEditor::offsetToLineCol (const std::string& text, size_t offset, int & line, int & col) {
270+ line = 0 ;
271+ col = 0 ;
272+ for (size_t i = 0 ; i < offset && i < text.size (); i++) {
273+ if (text[i] == ' \n ' ) { line++; col = 0 ; }
274+ else { col++; }
275+ }
276+ }
277+
234278void editor::CodeEditor::insertLuaEntityProperty (EditorInstance& instance, Entity entity, uint32_t entitySceneId) {
235279 // Resolve the source scene
236280 SceneProject* sourceSceneProject = project->getScene (entitySceneId);
@@ -243,7 +287,6 @@ void editor::CodeEditor::insertLuaEntityProperty(EditorInstance& instance, Entit
243287 if (!scene->isEntityCreated (entity)) return ;
244288
245289 // Get entity info
246- std::string entityName = scene->getEntityName (entity);
247290 std::string entityType = editor::ProjectUtils::getEntityTypeName (scene, entity);
248291
249292 // Check if the entity has a Lua script — use its className as a more specific type
@@ -257,26 +300,9 @@ void editor::CodeEditor::insertLuaEntityProperty(EditorInstance& instance, Entit
257300 }
258301 }
259302
260- // Generate variable name: sanitize entity name to camelCase
261- std::string varName;
262- bool nextUpper = false ;
263- for (char c : entityName) {
264- if (std::isalnum (static_cast <unsigned char >(c))) {
265- if (varName.empty ()) {
266- varName += (char )std::tolower (static_cast <unsigned char >(c));
267- } else if (nextUpper) {
268- varName += (char )std::toupper (static_cast <unsigned char >(c));
269- nextUpper = false ;
270- } else {
271- varName += c;
272- }
273- } else {
274- if (!varName.empty ()) nextUpper = true ;
275- }
276- }
277- if (varName.empty ()) varName = " entity" ;
303+ std::string varName = toCamelCase (scene->getEntityName (entity));
278304
279- // Avoid duplicate property names: check existing text for same variable name
305+ // Avoid duplicate property names
280306 std::string text = instance.editor ->GetText ();
281307 {
282308 std::string baseName = varName;
@@ -286,18 +312,7 @@ void editor::CodeEditor::insertLuaEntityProperty(EditorInstance& instance, Entit
286312 }
287313 }
288314
289- // Generate display name from varName
290- std::string displayName;
291- for (size_t i = 0 ; i < varName.size (); i++) {
292- if (i == 0 ) {
293- displayName += (char )std::toupper (static_cast <unsigned char >(varName[i]));
294- } else if (std::isupper (static_cast <unsigned char >(varName[i]))) {
295- displayName += ' ' ;
296- displayName += varName[i];
297- } else {
298- displayName += varName[i];
299- }
300- }
315+ std::string displayName = toDisplayName (varName);
301316
302317 // Build the Lua property entry text
303318 std::string propEntry =
@@ -351,11 +366,8 @@ void editor::CodeEditor::insertLuaEntityProperty(EditorInstance& instance, Entit
351366 }
352367
353368 // Insert before the closing brace of properties table using cursor-based insert (preserves undo)
354- int insertLine = 0 , insertCol = 0 ;
355- for (size_t i = 0 ; i < closePos; i++) {
356- if (text[i] == ' \n ' ) { insertLine++; insertCol = 0 ; }
357- else { insertCol++; }
358- }
369+ int insertLine, insertCol;
370+ offsetToLineCol (text, closePos, insertLine, insertCol);
359371 instance.editor ->SetCursorPosition (insertLine, insertCol);
360372 instance.editor ->InsertText (insertion, false );
361373
@@ -409,7 +421,6 @@ void editor::CodeEditor::insertCppEntityProperty(EditorInstance& instance, Entit
409421 if (!scene->isEntityCreated (entity)) return ;
410422
411423 // Get entity info
412- std::string entityName = scene->getEntityName (entity);
413424 std::string entityType = editor::ProjectUtils::getEntityTypeName (scene, entity);
414425
415426 // Check if the entity has a C++ SUBCLASS script — use its class name as a more specific type
@@ -429,24 +440,7 @@ void editor::CodeEditor::insertCppEntityProperty(EditorInstance& instance, Entit
429440 }
430441 }
431442
432- // Generate variable name: sanitize entity name to camelCase
433- std::string varName;
434- bool nextUpper = false ;
435- for (char c : entityName) {
436- if (std::isalnum (static_cast <unsigned char >(c))) {
437- if (varName.empty ()) {
438- varName += (char )std::tolower (static_cast <unsigned char >(c));
439- } else if (nextUpper) {
440- varName += (char )std::toupper (static_cast <unsigned char >(c));
441- nextUpper = false ;
442- } else {
443- varName += c;
444- }
445- } else {
446- if (!varName.empty ()) nextUpper = true ;
447- }
448- }
449- if (varName.empty ()) varName = " entity" ;
443+ std::string varName = toCamelCase (scene->getEntityName (entity));
450444
451445 // Determine header path: if currently viewing .cpp, derive .h path
452446 fs::path headerPath = instance.filepath ;
@@ -490,18 +484,7 @@ void editor::CodeEditor::insertCppEntityProperty(EditorInstance& instance, Entit
490484 }
491485 }
492486
493- // Generate display name from varName (camelCase -> "Camel Case")
494- std::string displayName;
495- for (size_t i = 0 ; i < varName.size (); i++) {
496- if (i == 0 ) {
497- displayName += (char )std::toupper (static_cast <unsigned char >(varName[i]));
498- } else if (std::isupper (static_cast <unsigned char >(varName[i]))) {
499- displayName += ' ' ;
500- displayName += varName[i];
501- } else {
502- displayName += varName[i];
503- }
504- }
487+ std::string displayName = toDisplayName (varName);
505488
506489 // Build the SPROPERTY + member declaration
507490 std::string typeDecl = isSubclassType ? entityType : (" doriax::" + entityType);
@@ -580,22 +563,16 @@ void editor::CodeEditor::insertCppEntityProperty(EditorInstance& instance, Entit
580563 // Must do #include first so it doesn't shift SPROPERTY position calculation
581564 int includeLineShift = 0 ;
582565 if (needsInclude && includeInsertPos != std::string::npos) {
583- int incLine = 0 , incCol = 0 ;
584- for (size_t i = 0 ; i < includeInsertPos; i++) {
585- if (headerText[i] == ' \n ' ) { incLine++; incCol = 0 ; }
586- else { incCol++; }
587- }
566+ int incLine, incCol;
567+ offsetToLineCol (headerText, includeInsertPos, incLine, incCol);
588568 headerInstance->editor ->SetCursorPosition (incLine, incCol);
589569 headerInstance->editor ->InsertText (includeDirective + " \n " , false );
590570 includeLineShift = 1 ; // One extra line added
591571 }
592572
593573 // Now insert SPROPERTY at the adjusted position
594- int insertLine = 0 , insertCol = 0 ;
595- for (size_t i = 0 ; i < insertPos; i++) {
596- if (headerText[i] == ' \n ' ) { insertLine++; insertCol = 0 ; }
597- else { insertCol++; }
598- }
574+ int insertLine, insertCol;
575+ offsetToLineCol (headerText, insertPos, insertLine, insertCol);
599576 // Shift if #include was inserted before this position
600577 if (needsInclude && includeInsertPos != std::string::npos && includeInsertPos <= insertPos) {
601578 insertLine += includeLineShift;
@@ -606,8 +583,6 @@ void editor::CodeEditor::insertCppEntityProperty(EditorInstance& instance, Entit
606583 // Update the properties dynamically parsing the current text, without overwriting the file
607584 headerInstance->isModified = true ;
608585 headerInstance->propertyInsertUndoIndex = headerInstance->editor ->GetUndoIndex ();
609- std::string finalHeaderText = headerInstance->editor ->GetText ();
610- updateScriptProperties (*headerInstance, finalHeaderText);
611586 } else {
612587 // Header not open in editor — build full text and write to disk
613588 // Apply #include first (modifies headerText), then insert SPROPERTY
@@ -636,14 +611,9 @@ void editor::CodeEditor::insertCppEntityProperty(EditorInstance& instance, Entit
636611
637612 uint32_t storedSceneId = (entitySceneId != selectedScene->id ) ? entitySceneId : 0 ;
638613
639- std::string inMemoryContent = " " ;
640- if (headerInstance) {
641- inMemoryContent = headerInstance->editor ->GetText ();
642- } else {
643- // We already wrote it to disk, but we also can fallback to reading from disk because inMemoryContent is empty
644- }
614+ std::string inMemoryContent = headerInstance ? headerInstance->editor ->GetText () : " " ;
645615
646- // First, trigger updateScriptProperties for all entities referencing this header
616+ // Update script properties and link the dropped entity for all entities referencing this header
647617 for (auto & sceneProject : project->getScenes ()) {
648618 if (!sceneProject.scene ) continue ;
649619
0 commit comments